26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
53 #pragma package(smart_init)
72 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
73 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
74 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
75 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
76 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
77 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
88 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
89 AnsiString(TrainModeIn));
135 for(
int x = 0; x < 4; x++)
144 for(
int x = 0; x < 4; x++)
153 for(
int x = 0; x < 4; x++)
158 for(
int x = 0; x < 4; x++)
162 for(
int x = 0; x < 3; x++)
199 for(
int x = 0; x < 4; x++)
258 throw Exception(
"Error in attempting to delete FrontCodePtr");
262 for(
int x = 0; x < 4; x++)
266 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
271 for(
int x = 0; x < 4; x++)
275 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
304 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
370 bool TempDerail =
false;
416 else if((NextElementPosition > -1) && (NextEntryPos > -1))
487 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
497 for(
int x = 0; x < 4; x++)
504 for(
int x = 0; x < 4; x++)
765 int LockedVectorNumber;
894 AnsiString ReasonArray[24] = {
"a driver is awaited",
"a guard is awaited",
"of a medical emergency",
"of a technical problem",
"of a security issue",
895 "of a safety issue",
"of a disturbance",
"a train crew member has been taken ill",
"the driver has been taken ill",
"the guard has been taken ill",
896 "a report has been received concerning safety",
"a shoe has been lost under the train",
"of a reported theft",
897 "of an incident involving an animal",
"some luggage has been lost under the train",
"a minor repair is needed",
"a suspicious object has to be dealt with safely",
898 "a door is stuck open",
"additional stock has to be attached",
"a security alert",
"of a train fault",
"of an operating incident",
"safety checks are required",
899 "of a shortage of on train crew"};
906 if(DwellTime < TDateTime(30.0 / 86400))
908 DwellTime = TDateTime(30.0 / 86400);
910 int randval = random(10000);
915 if(randval < Utilities->MinorDelayCutoff)
922 if(randval < Utilities->ModerateDelayCutoff)
929 if(randval < Utilities->MajorDelayCutoff)
944 if(
NewDelay <
double(DwellTime) * 1440)
950 NewDelay -= double(DwellTime) * 1440;
1011 int randval2 = rand() % 24;
1012 AnsiString Reason = ReasonArray[randval2];
1015 " minutes because " + Reason);
1017 " minutes because " + Reason);
1023 " minutes because of a minor problem");
1025 " minutes because of a minor problem");
1175 if(BufferLocation ==
"")
1180 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1242 int NextElementPosition, NextEntryPos;
1266 NextElementPosition = -1;
1269 if((NextElementPosition > -1) && (NextEntryPos > -1))
1391 AnsiString StationName;
1402 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1415 if((NextElementPosition > -1) && (NextEntryPos > -1))
1549 if(TIFEntryPos == 0)
1586 if(NextElementPosition > -1)
1623 AnsiString Loc =
"";
1624 bool LocNamed =
false;
1653 Loc =
"outside railway";
1685 NextElementPosition = -1;
1696 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1714 if((NextElementPosition > -1) && (NextEntryPos > -1))
1752 FirstPair.second).
GetELink() == TempELink))
1757 SecondPair.second).
GetELink() == TempELink))
1771 FirstPair.second).
GetELink() == TempELink))
1776 SecondPair.second).
GetELink() == TempELink))
1790 FirstPair.second).
GetELink() == TempELink))
1795 SecondPair.second).
GetELink() == TempELink))
1825 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1828 int NewLastElement = 0, NewLastExitPos = 0;
1846 if(NewLastElement == -1)
1852 if(NewLastExitPos == -1)
1856 LastElement = NewLastElement;
1857 LastExitPos = NewLastExitPos;
1860 if(CumDistance < 1200)
1866 int FirstDistance = 0;
1867 if(CumDistance >= 1200)
1869 FirstDistance = 100;
1873 FirstDistance = 1200 - CumDistance;
1875 if(FirstDistance < 100)
1877 FirstDistance = 100;
1903 if(VectorIT->RouteNumber == RouteNumber)
1940 " failed when changing aspect.\nTrains can only pass under signaller control.");
1974 LockedVectorNumber)))
2133 for(
int x = 0; x < 4; x++)
2140 for(
int x = 0; x < 4; x++)
2166 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
2171 if(OtherTrainEntryPos == -1)
2173 throw Exception(
"Error - OtherTrainEntryPos not set");
2192 int OtherTrainID = -1;
2193 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2284 bool StopRequired =
false;
2297 int NextElementEntryPos = -1;
2298 int NextElementExitPos = -1;
2299 bool TrainOnNextElement =
false;
2300 bool StopSignalAtNextElement =
false;
2301 if(ForwardConnection)
2309 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2311 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2367 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2580 if(Code.Length() != 4)
2584 for(
int x = 1; x < 5; x++)
2591 for(
int x = 0; x < 4; x++)
2754 throw Exception(
"Error in GetOffsetValues - Link value wrong");
2767 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
2782 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
2791 TRect SourceRect, DestRect;
2793 DestRect.init(0, 0, 8, 8);
2796 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
2798 TempGraphic->PixelFormat = pf8bit;
2799 TempGraphic->Width = 16;
2800 TempGraphic->Height = 16;
2806 TempGraphic->Transparent =
true;
2810 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2811 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2817 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2825 else if(TempElement.
SpeedTag == 89)
2829 else if(TempElement.
SpeedTag == 90)
2833 else if(TempElement.
SpeedTag == 91)
2837 else if(TempElement.
SpeedTag == 92)
2841 else if(TempElement.
SpeedTag == 93)
2845 else if(TempElement.
SpeedTag == 94)
2849 else if(TempElement.
SpeedTag == 95)
2853 TempGraphic->Transparent =
true;
2857 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2858 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2860 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2867 for(
int x = 0; x < 40; x++)
2882 TempGraphic->Transparent =
true;
2886 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2887 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2889 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2903 TempGraphic->Transparent =
true;
2907 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2908 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2912 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
2915 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2920 TempGraphic->Transparent =
true;
2924 int BDVectorPos = -1;
2933 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2938 TempGraphic->Transparent =
true;
2942 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2943 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2945 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2951 TempGraphic->Transparent =
true;
2955 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2956 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2958 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3224 throw Exception(
"Error, same train on two different bridge tracks");
3270 AnsiString(EntryPos) +
"," +
HeadCode);
3287 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3306 AnsiString(EntryPos) +
"," +
HeadCode);
3315 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3348 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3349 int LockedVectorNumber;
3362 TRect SourceRect, DestRect;
3363 DestRect.init(0, 0, 8, 8);
3370 int FirstELink, SecondELink = -1;
3373 if(RoutePair2.first > -1)
3382 if(SecondELink == -1)
3384 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3389 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3399 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3400 DestGraphic->PixelFormat = pf8bit;
3401 DestGraphic->Width = 8;
3402 DestGraphic->Height = 8;
3403 DestGraphic->Transparent =
true;
3406 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3415 PrefDirElement, LockedVectorNumber))
3430 if(ElementEntryPos > 1)
3452 AnsiString(EntryPos) +
"," +
HeadCode);
3454 bool WrongRoute =
false;
3480 int LinkNumber = TrackElement.
Link[EntryPos];
3481 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3486 bool LogActionErrorCalled =
false;
3496 LogActionErrorCalled =
true;
3513 else if(LinkNumber == 3)
3521 LogActionErrorCalled =
true;
3538 else if(LinkNumber == 7)
3546 LogActionErrorCalled =
true;
3563 else if(LinkNumber == 9)
3571 LogActionErrorCalled =
true;
3603 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3608 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3618 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3623 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3632 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
3653 bool ColourError =
false, ColourError2 =
false;
3658 ColourError2 =
true;
3660 for(
int x = 0; x < 4; x++)
3665 ColourError2 =
true;
3671 "ERROR: Colour depth insufficient to display train colours properly. Please ensure that the 'safe' (web) palette of 256 colours can be displayed");
3675 for(
int x = 0; x < 4; x++)
3762 AnsiString(EntryPos) +
"," +
HeadCode);
3763 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
3764 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
3765 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
3766 TrainInFrontInSignallerModeFlag =
false;
3767 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
3768 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
3769 bool SignallerStopRequired =
false;
3780 if(CurrentTrackVectorPosition > -1)
3784 if((EntryPos == 0) || (EntryPos == 2))
3797 else if(EntryPos == 1)
3821 EntryHalfLength = CurrentElementHalfLength;
3826 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
3830 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
3877 FrontElementMaxSpeed = LimitingSpeed;
3913 double ExitSpeedAtMaxBraking;
3918 ExitSpeedAtMaxBraking = 0;
3928 if(ExitSpeedAtMaxBraking > LimitingSpeed)
3930 SpeedToUse = ExitSpeedAtMaxBraking;
3934 SpeedToUse = LimitingSpeed;
3949 RedSignalFlag =
false;
3950 BuffersFlag =
false;
3951 StationFlag =
false;
3952 BuffersOrContinuationNowFlag =
false;
3953 ContinuationNextFlag =
false;
3956 CumulativeLength += (2 * CurrentElementHalfLength);
3959 SignallerStopRequired =
true;
3981 bool StopRequired =
false;
3995 StationFlag =
false;
4001 BuffersOrContinuationNowFlag =
true;
4003 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
4007 if((EntryPos == 0) || (EntryPos == 2))
4029 if(NextTrackVectorPosition > -1)
4034 if((NextEntryPos == 0) || (NextEntryPos == 2))
4047 else if(NextEntryPos == 1)
4060 if(NextEntryPos > 1)
4074 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
4086 RedSignalFlag =
true;
4108 TrainInFrontInSignallerModeFlag =
true;
4132 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
4144 double MaxHalfSpeed;
4148 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
4150 MaxHalfSpeed = FrontElementMaxSpeed;
4154 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
4162 bool HalfSpeedLimited =
false;
4166 HalfSpeedLimited =
true;
4196 if(HalfSpeedLimited)
4221 if(SignallerStopRequired)
4237 int TempMaxExitSpeed;
4240 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4242 MaxExitSpeedAtHalfBraking = 0;
4246 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4250 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4252 TempMaxExitSpeed = FrontElementMaxSpeed;
4256 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4268 if(ExitSpeedHalfSquared < 10)
4278 if(ExitSpeedFullSquared < 10)
4350 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4351 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4375 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4376 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4386 if(!BuffersOrContinuationNowFlag)
4388 if(NextSpeedLimit < LimitingSpeed)
4390 LimitingSpeed = NextSpeedLimit;
4394 int TempMaxExitSpeed;
4398 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4400 MaxExitSpeedAtHalfBraking = 0;
4404 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4406 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4408 TempMaxExitSpeed = FrontElementMaxSpeed;
4412 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4423 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4436 if(!BuffersOrContinuationNowFlag)
4438 CurrentTrackVectorPosition = NextTrackVectorPosition;
4439 EntryPos = NextEntryPos;
4440 CurrentElementHalfLength = NextElementHalfLength;
4443 ContinuationNextFlag =
true;
4447 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4467 if(ExitSpeedHalfSquared < 10)
4477 if(ExitSpeedFullSquared < 10)
4540 double DeltaExitTimeToMaxInSecs;
4541 double DistanceToMax;
4550 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4552 DistanceToMax = EntryHalfLength;
4555 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4556 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4573 double DeltaExitTimeToMaxInSecs;
4574 double DistanceToMax;
4583 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4585 DistanceToMax = EntryHalfLength / 2;
4588 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4589 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4600 if(ExitSpeedHalfSquared < 10)
4610 if(ExitSpeedFullSquared < 10)
4629 if((EntryPos == 0) || (EntryPos == 2))
4651 if(NextTrackVectorPosition > -1)
4653 int NextElementLength;
4654 if(NextEntryPos > 1)
4662 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
4849 int ElementCount = 0;
4857 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
4875 CurrentTrackVectorPosition).
Attribute != 4))
4915 if((EntryPos == 0) || (EntryPos == 2))
4937 CurrentTrackVectorPosition = NextTrackVectorPosition;
4938 EntryPos = NextEntryPos;
4940 if(ElementCount > 1000)
4968 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
4993 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
4994 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
4995 int RouteStartPosition;
4997 int PlatformPosition;
4999 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
5015 if(Distance > (4000 + LeadElementDistance))
5038 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
5041 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
5087 if(!PlatformFoundFlag)
5089 PlatformPosition = CurrentTrackVectorPosition;
5092 PlatformFoundFlag =
true;
5108 if((EntryPos == 0) || (EntryPos == 2))
5152 if(ElementNumber < 2)
5154 SkipRouteCheck =
true;
5158 SkipRouteCheck =
false;
5160 if(ElementNumber == 1)
5162 RouteStartPosition = CurrentTrackVectorPosition;
5172 if(ElementNumber > 1)
5176 RouteOrPartRouteSet =
true;
5180 RouteOrPartRouteSet =
false;
5183 if(!SkipRouteCheck && !RouteOrPartRouteSet)
5190 int ExitLink = CurrentTrackElement.
Link[ExitPos];
5191 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
5203 Distance += CurrentTrackElement.
Length01;
5207 Distance += CurrentTrackElement.
Length23;
5209 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
5210 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
5211 CurrentTrackVectorPosition = NextTrackVectorPosition;
5212 EntryPos = NextEntryPos;
5249 return(RepeatHeadCode);
5271 bool FrontValid =
false, RearValid =
false;
5272 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
5276 TrainToBeJoinedBy = NULL;
5290 int TrainToBeJoinedByID = -1;
5311 if((TrainToBeJoinedByID < 0) && RearValid)
5330 if(TrainToBeJoinedByID < 0)
5332 TrainToBeJoinedBy = NULL;
5337 if(!TrainToBeJoinedBy->
Stopped())
5339 TrainToBeJoinedBy = NULL;
5350 TDateTime TimetableNonRepeatTime,
bool Warning)
5386 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5387 AnsiString BaseLog =
"", WarningBaseLog =
"", PerfLog =
"", ActionLog =
"";
5388 int IntMinsLate = 0;
5393 ActionLog =
" arrived at ";
5402 ActionLog =
" terminated at ";
5407 ActionLog =
" departed from ";
5409 if(ActionType ==
Pass)
5411 ActionLog =
" passed ";
5415 ActionLog =
" created at ";
5417 if(ActionType ==
Enter)
5419 ActionLog =
" entered railway at ";
5425 if(ActionType ==
Leave)
5427 ActionLog =
" left railway at ";
5431 ActionLog =
" split from front to ";
5435 ActionLog =
" split from rear to ";
5439 ActionLog =
" joined by ";
5443 ActionLog =
" changed direction at ";
5447 ActionLog =
" became new service ";
5451 ActionLog =
" taken under signaller control at ";
5455 ActionLog =
" restored to timetable control at ";
5461 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5465 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5469 ActionLog =
" REMOVED FROM RAILWAY at ";
5474 ActionLog =
" received signaller authority to proceed";
5478 ActionLog =
" received signaller authority to step forward";
5482 ActionLog =
" changed direction under signaller control at ";
5486 ActionLog =
" received signaller authority to pass stop signal";
5490 ActionLog =
" received signaller instruction to stop";
5494 ActionLog =
" stopped on signaller instruction ";
5498 ActionLog =
" joined under signaller control by ";
5502 ActionLog =
" suffered an onboard power failure at ";
5506 ActionLog =
" failure repaired at ";
5510 ActionLog =
" left railway under signaller control at ";
5512 if(OtherHeadCode !=
"")
5514 OtherHeadCode +=
" at ";
5527 bool TimePerformance =
true;
5535 TimePerformance =
false;
5539 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
5541 if(ActionType ==
Pass)
5555 IntMinsLate = int(ceil(MinsLate));
5559 IntMinsLate = int(floor(MinsLate));
5561 if(IntMinsLate == 0)
5563 PerfLog =
" on time";
5565 else if(IntMinsLate == 1)
5567 PerfLog =
" 1 minute late";
5569 else if(IntMinsLate == -1)
5571 PerfLog =
" 1 minute early";
5573 else if(IntMinsLate > 1)
5575 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
5577 else if(IntMinsLate < -1)
5579 int PosIntMinsLate = -IntMinsLate;
5580 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
5582 if(LocationName.Pos(
'-') > 0)
5584 PerfLog =
"," + PerfLog;
5598 if((ActionType ==
Arrive) && (IntMinsLate == 0))
5602 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
5607 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
5613 else if((ActionType ==
Pass) && (IntMinsLate == 0))
5617 else if((ActionType ==
Pass) && (IntMinsLate > 0))
5622 else if((ActionType ==
Pass) && (IntMinsLate < 0))
5628 else if((ActionType ==
Leave) && (IntMinsLate == 0))
5632 else if((ActionType ==
Leave) && (IntMinsLate > 0))
5637 else if((ActionType ==
Leave) && (IntMinsLate < 0))
5643 else if((ActionType ==
Depart) && (IntMinsLate == 0))
5647 else if((ActionType ==
Depart) && (IntMinsLate > 0))
5666 AnsiString LocName =
"";
5733 if(LocationName ==
"")
5737 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5738 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5739 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5743 if(LocationName !=
"")
5751 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5756 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5770 int LeadPosA = FirstNamedElementPos;
5771 int LeadPosB = FirstNamedLinkedElementPos;
5772 int LeadPosC = SecondNamedElementPos;
5773 int LeadPosD = SecondNamedLinkedElementPos;
5775 int LeadNumAtLoc = 0;
5792 if(LeadNumAtLoc < 4)
5796 SecondNamedLinkedElementPos))
5798 FirstNamedElementPos = LeadPosA;
5799 FirstNamedLinkedElementPos = LeadPosB;
5800 SecondNamedElementPos = LeadPosC;
5801 SecondNamedLinkedElementPos = LeadPosD;
5805 int MidNumAtLoc = 0;
5822 if(LeadNumAtLoc > MidNumAtLoc)
5825 FirstNamedElementPos = LeadPosA;
5826 FirstNamedLinkedElementPos = LeadPosB;
5827 SecondNamedElementPos = LeadPosC;
5828 SecondNamedLinkedElementPos = LeadPosD;
5842 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5852 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5853 FrontTrainRearPosition = FirstNamedElementPos;
5854 RearTrainFrontPosition = SecondNamedElementPos;
5855 RearTrainRearPosition = SecondNamedLinkedElementPos;
5859 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5860 FrontTrainRearPosition = SecondNamedElementPos;
5861 RearTrainFrontPosition = FirstNamedElementPos;
5862 RearTrainRearPosition = FirstNamedLinkedElementPos;
5869 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5870 FrontTrainRearPosition = SecondNamedElementPos;
5871 RearTrainFrontPosition = FirstNamedElementPos;
5872 RearTrainRearPosition = FirstNamedLinkedElementPos;
5876 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5877 FrontTrainRearPosition = FirstNamedElementPos;
5878 RearTrainFrontPosition = SecondNamedElementPos;
5879 RearTrainRearPosition = SecondNamedLinkedElementPos;
5882 RearTrainExitPos = -1;
5883 for(
int x = 0; x < 4; x++)
5887 RearTrainExitPos = x;
5891 if(RearTrainExitPos == -1)
5893 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in FrontTrainSplit");
5895 FrontTrainExitPos = -1;
5896 for(
int x = 0; x < 4; x++)
5900 FrontTrainExitPos = x;
5904 if(FrontTrainExitPos == -1)
5906 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in FrontTrainSplit");
5909 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
5916 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
5936 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
5944 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
5945 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
5946 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
5985 double NewTrainPowerAtRail;
5991 NewTrainMass =
Mass * double(MassPercent)/100.0;
5993 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
5994 if(NewTrainPowerAtRail == 0)
5996 NewTrainPowerAtRail = 0.08;
6004 NewTrainMass =
Mass;
6078 if(LocationName ==
"")
6082 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
6083 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
6084 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
6088 if(LocationName !=
"")
6095 SecondNamedLinkedElementPos))
6099 SecondNamedLinkedElementPos))
6113 int LeadPosA = FirstNamedElementPos;
6114 int LeadPosB = FirstNamedLinkedElementPos;
6115 int LeadPosC = SecondNamedElementPos;
6116 int LeadPosD = SecondNamedLinkedElementPos;
6118 int LeadNumAtLoc = 0;
6135 if(LeadNumAtLoc < 4)
6139 SecondNamedLinkedElementPos))
6141 FirstNamedElementPos = LeadPosA;
6142 FirstNamedLinkedElementPos = LeadPosB;
6143 SecondNamedElementPos = LeadPosC;
6144 SecondNamedLinkedElementPos = LeadPosD;
6148 int MidNumAtLoc = 0;
6165 if(LeadNumAtLoc > MidNumAtLoc)
6168 FirstNamedElementPos = LeadPosA;
6169 FirstNamedLinkedElementPos = LeadPosB;
6170 SecondNamedElementPos = LeadPosC;
6171 SecondNamedLinkedElementPos = LeadPosD;
6185 throw Exception(
"Error - LocationName not set in RearTrainSplit");
6195 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
6196 FrontTrainRearPosition = FirstNamedElementPos;
6197 RearTrainFrontPosition = SecondNamedElementPos;
6198 RearTrainRearPosition = SecondNamedLinkedElementPos;
6202 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
6203 FrontTrainRearPosition = SecondNamedElementPos;
6204 RearTrainFrontPosition = FirstNamedElementPos;
6205 RearTrainRearPosition = FirstNamedLinkedElementPos;
6212 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
6213 FrontTrainRearPosition = SecondNamedElementPos;
6214 RearTrainFrontPosition = FirstNamedElementPos;
6215 RearTrainRearPosition = FirstNamedLinkedElementPos;
6219 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
6220 FrontTrainRearPosition = FirstNamedElementPos;
6221 RearTrainFrontPosition = SecondNamedElementPos;
6222 RearTrainRearPosition = SecondNamedLinkedElementPos;
6225 RearTrainExitPos = -1;
6226 for(
int x = 0; x < 4; x++)
6230 RearTrainExitPos = x;
6234 if(RearTrainExitPos == -1)
6236 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in RearTrainSplit");
6238 FrontTrainExitPos = -1;
6239 for(
int x = 0; x < 4; x++)
6243 FrontTrainExitPos = x;
6247 if(FrontTrainExitPos == -1)
6249 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in RearTrainSplit");
6252 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
6259 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
6279 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
6287 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
6288 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
6289 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
6327 double NewTrainPowerAtRail;
6333 NewTrainMass =
Mass * double(MassPercent)/100.0;
6335 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
6336 if(NewTrainPowerAtRail == 0)
6338 NewTrainPowerAtRail = 0.08;
6346 NewTrainMass =
Mass;
6465 TTrain *TrainToBeJoinedBy;
6498 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6500 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6561 int RouteNumber = -1;
6566 int CorrectRouteID = OR.
RouteID;
6571 bool FirstPass =
true;
6576 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6690 for(
int x = 0; x < IncNum; x++)
6723 else if(Ptr->
Command ==
"jbo")
6728 else if(Ptr->
Command ==
"dsc")
6739 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6745 bool IncludeFER =
false;
6753 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6758 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6769 else if(Ptr->
Command ==
"Fjo")
6775 else if(Ptr->
Command ==
"Frh")
6785 else if(Ptr->
Command ==
"Frh-sh")
6836 else if(Ptr->
Command ==
"jbo")
6841 else if(Ptr->
Command ==
"dsc")
6846 else if(Ptr->
Command ==
"cdt")
6854 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
7251 int RouteNumber = -1;
7256 int CorrectRouteID = OR.
RouteID;
7261 bool FirstPass =
true;
7266 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
7294 ",FloatingLabelNextString" +
"," +
HeadCode);
7295 AnsiString RetStr =
"", LocationName =
"";
7298 if(ActionTime == TDateTime(-1))
7302 if(ActionTime == TDateTime(-1))
7308 if(ActionTime != TDateTime(-1))
7316 throw Exception(
"Error - start entry in FloatingLabelNextString");
7360 else if(Ptr->
Command ==
"Fns")
7366 else if(Ptr->
Command ==
"F-nshs")
7397 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7399 else if(Ptr->
Command ==
"Frh")
7401 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7403 else if(Ptr->
Command ==
"Fer")
7405 AnsiString AllowedExits =
"";
7408 else if(Ptr->
Command ==
"Fjo")
7413 else if(Ptr->
Command ==
"jbo")
7418 else if(Ptr->
Command ==
"fsp")
7423 else if(Ptr->
Command ==
"rsp")
7428 else if(Ptr->
Command ==
"cdt")
7432 else if(Ptr->
Command ==
"dsc")
7441 throw Exception(
"Error - start entry in FloatingLabelNextString where TTClockTime > ActionTime");
7485 else if(Ptr->
Command ==
"Fns")
7491 else if(Ptr->
Command ==
"F-nshs")
7522 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7524 else if(Ptr->
Command ==
"Frh")
7526 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7528 else if(Ptr->
Command ==
"Fer")
7530 AnsiString AllowedExits =
"";
7533 else if(Ptr->
Command ==
"Fjo")
7538 else if(Ptr->
Command ==
"jbo")
7543 else if(Ptr->
Command ==
"fsp")
7548 else if(Ptr->
Command ==
"rsp")
7553 else if(Ptr->
Command ==
"cdt")
7557 else if(Ptr->
Command ==
"dsc")
7566 throw Exception(
"Error - start entry in FloatingLabelNextString in final 'else'");
7610 else if(Ptr->
Command ==
"Fns")
7616 else if(Ptr->
Command ==
"F-nshs")
7647 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7649 else if(Ptr->
Command ==
"Frh")
7651 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7653 else if(Ptr->
Command ==
"Fer")
7655 AnsiString AllowedExits =
"";
7658 else if(Ptr->
Command ==
"Fjo")
7663 else if(Ptr->
Command ==
"jbo")
7668 else if(Ptr->
Command ==
"fsp")
7673 else if(Ptr->
Command ==
"rsp")
7678 else if(Ptr->
Command ==
"cdt")
7682 else if(Ptr->
Command ==
"dsc")
7826 + AnsiString(RptNum) +
",GetNewServiceDepartureInfo," +
HeadCode);
7827 AnsiString DepTime =
"", EventTime =
"";
7828 bool CDTFlag =
false;
7830 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
7831 AnsiString TowardsLocation =
"";
7834 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
7836 TowardsLocation = AVI->LocationName;
7838 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
7847 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
7854 if(AVI->Command ==
"cdt")
7859 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
7874 RetStr +=
"\nNew service splits at approx. " + EventTime;
7878 if(AVI->Command ==
"jbo")
7893 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at approx. " + EventTime;
7897 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
7912 RetStr +=
"\nNew service finishes and forms another new service at approx. " + EventTime;
7916 if(AVI->Command ==
"Fjo")
7931 RetStr +=
"\nNew service finishes and joins " + AVI->OtherHeadCode +
" at approx. " + EventTime;
7935 if(AVI->Command ==
"Frh")
7937 RetStr +=
"\nNew service finishes and remains at the location.";
7941 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
7948 if(TowardsLocation !=
"")
7950 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
7954 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
7959 if(TowardsLocation !=
"")
7961 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
7965 RetStr +=
"\nNew service departs at " + DepTime;
7974 if(TowardsLocation !=
"")
7976 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
7980 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
7985 if(TowardsLocation !=
"")
7987 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
7991 RetStr +=
"\nNew service departs at approx. " + DepTime;
8008 if(TowardsLocation !=
"")
8010 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
8014 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
8019 if(TowardsLocation !=
"")
8021 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
8025 RetStr +=
"\nNew service departs at approx. " + DepTime;
8044 ",FloatingTimetableString" +
"," +
HeadCode);
8045 AnsiString RetStr =
"", PartStr =
"";
8047 bool SkipDep =
false, SkipDepActedOn =
false;
8053 throw Exception(
"Error - start entry in FloatingTimetableString");
8056 bool FirstPass =
true;
8069 AnsiString TrainLoc =
"";
8115 AnsiString TrainLoc =
"";
8155 else if(Ptr->
Command ==
"Fns")
8161 else if(Ptr->
Command ==
"F-nshs")
8194 else if(Ptr->
Command ==
"Frh")
8198 else if(Ptr->
Command ==
"Fer")
8200 AnsiString AllowedExits =
"";
8203 else if(Ptr->
Command ==
"Fjo")
8208 else if(Ptr->
Command ==
"jbo")
8213 else if(Ptr->
Command ==
"fsp")
8223 PartStr+=
", split mass%-Power% = 50-50";
8226 else if(Ptr->
Command ==
"rsp")
8236 PartStr+=
", split mass%-Power% = 50-50";
8239 else if(Ptr->
Command ==
"cdt")
8243 else if(Ptr->
Command ==
"dsc")
8249 RetStr = RetStr +
'\n' + PartStr;
8263 SkipDepActedOn =
true;
8274 RetStr =
"Timetable finished";
8278 RetStr =
"No timetable";
8282 return(
"Timetable:\n" + RetStr);
8435 bool ForwardHeadCode;
8439 ForwardHeadCode =
true;
8444 ForwardHeadCode =
false;
8587 if(ColourNumber == 0)
8591 else if(ColourNumber == 1)
8595 else if(ColourNumber == 2)
8599 else if(ColourNumber == 3)
8603 else if(ColourNumber == 4)
8607 else if(ColourNumber == 5)
8611 else if(ColourNumber == 6)
8615 else if(ColourNumber == 7)
8619 else if(ColourNumber == 8)
8623 else if(ColourNumber == 9)
8627 else if(ColourNumber == 10)
8631 else if(ColourNumber == 11)
8635 else if(ColourNumber == 12)
8639 else if(ColourNumber == 13)
8643 else if(ColourNumber == 14)
8655 for(
int x = 0; x < 4; x++)
8662 for(
int x = 0; x < 4; x++)
8747 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
8750 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
8751 bool GiveMessagesFalse =
false;
8752 bool CheckLocationsExistInRailwayTrue =
true;
8759 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
8762 if(Marker[6] ==
'1')
9227 bool HideFlashingTrain =
true;
9230 Graphics::TBitmap *SmallTrainBitmap;
9271 HideFlashingTrain =
false;
9276 HideFlashingTrain =
false;
9281 HideFlashingTrain =
false;
9286 HideFlashingTrain =
false;
9291 HideFlashingTrain =
false;
9295 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
9299 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
9323 for(
int y = 0; y < 3; y++)
9327 bool FoundFlag =
false;
9338 if(IMPair.first != IMPair.second)
9365 if((LocationName ==
"") && (
MidElement > -1))
9369 if((LocationName ==
"") && (
LagElement > -1))
9373 if(LocationName ==
"")
9375 throw Exception(
"Error - Location name not set in TrainAtLocation");
9386 for(
int x = 0; x < 4; x++)
9398 for(
int x = 0; x < 4; x++)
9415 AnsiString(LinkNumber) +
"," +
HeadCode);
9467 int DistanceToRedSignal = 0, DistanceToExit = -1;
9468 float TimeToAct = 0, LastTimeToExit =
TimeToExit;
9472 float MinsEarly = 0;
9473 TDateTime DepartureTime;
9474 TDateTime ArrivalTime;
9502 if(TempTTE < LastTimeToExit)
9537 if(TempTTE < LastTimeToExit)
9560 if(TempTTE < LastTimeToExit)
9590 if(TempTTE < LastTimeToExit)
9613 if(TempTTE < LastTimeToExit)
9656 float CurrentStopTime;
9657 float LaterStopTime;
9658 float RecoverableTime;
9666 if((DistanceToRedSignal == -1) && (DistanceToExit == -1))
9673 bool DistanceToRedSignalSet = (DistanceToRedSignal > -1);
9674 bool DistanceToExitSet = (DistanceToExit > -1);
9675 int GenericDistance = DistanceToRedSignal;
9676 if(DistanceToExitSet)
9678 GenericDistance = DistanceToExit;
9694 float TimeToSubtract, TotalStopTime;
9697 TimeToSubtract = RecoverableTime;
9740 if(CurrentStopTime > 0)
9742 TotalStopTime = CurrentStopTime + LaterStopTime;
9751 else if((MinsEarly > 0) && !
Stopped())
9753 TotalStopTime = LaterStopTime + MinsEarly;
9757 if(LaterStopTime == 0)
9759 TotalStopTime = CurrentStopTime;
9765 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
9768 if(AvTrackSpeed < 30)
9772 int Speed = AvTrackSpeed;
9782 if(DistanceToRedSignalSet)
9784 TimeToAct = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9794 TimeToExit = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9823 if((NextEntryPos == 0) || (NextEntryPos == 2))
9950 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9992 int IncrementalMinutes = 0;
9993 int IncrementalDigits = 0;
10001 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
10036 if(AVEntry0.
Command ==
"Snt-sh")
10041 int IncrementalMinutes = 0;
10042 int IncrementalDigits = 0;
10050 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
10093 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10173 AnsiString Loc =
"";
10174 bool ElementFound =
false;
10179 ElementFound =
true;
10184 ElementFound =
true;
10189 ElementFound =
true;
10218 else if(AVEntryPtr->
Command ==
"Fer")
10220 bool CorrectExit =
false;
10227 CorrectExit =
true;
10332 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10350 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10365 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10376 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
10377 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
10378 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
10380 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
10381 "," + AnsiString(Mass) +
"," + ModeStr);
10383 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr);
10385 int RearExitPos = -1;
10387 for(
int x = 0; x < 4; x++)
10394 if(RearExitPos == -1)
10396 throw Exception(
"Error, RearExit == -1 in AddTrain");
10398 bool ReportFlag =
true;
10403 ReportFlag =
false;
10415 if(ModeStr ==
"Timetable")
10421 if(MaxRunningSpeed < 10)
10423 MaxRunningSpeed = 10;
10425 if(SignallerSpeed < 10)
10427 SignallerSpeed = 10;
10429 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
10430 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
10437 if(SignallerControl)
10467 if(!SignallerControl)
10482 if(!SignallerControl)
10493 AnsiString Loc =
"";
10510 if(!SignallerControl)
10529 int RouteNumber = -1;
10530 bool SignalsSet =
false;
10537 int RouteStartPosition;
10541 if(FirstPair.first == RouteNumber)
10543 RouteStartPosition = FirstPair.second;
10545 else if(SecondPair.first == RouteNumber)
10547 RouteStartPosition = SecondPair.second;
10551 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
10557 else if(RouteNumber > -1)
10577 int LinkedRouteNumber = -1;
10598 int RouteStartPosition;
10602 if(FirstPair.first == RouteNumber)
10604 RouteStartPosition = FirstPair.second;
10606 else if(SecondPair.first == RouteNumber)
10608 RouteStartPosition = SecondPair.second;
10612 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
10618 else if(RouteNumber > -1)
10638 int LinkedRouteNumber = -1;
10659 AnsiString(TrackVectorNumber));
10662 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10671 throw Exception(
"Error, VecPos not set in EntryPos");
10673 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
10678 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
10683 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
10697 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10705 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
10715 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10736 return(RepeatTime);
10745 AnsiString RetStr =
"", PartStr =
"";
10753 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
10761 if(Ptr->SignallerControl)
10763 RetStr =
"Train under signaller control";
10768 if(Ptr->ArrivalTime == Ptr->DepartureTime)
10779 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
10783 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
10787 else if(Ptr->FormatType ==
PassTime)
10791 else if(Ptr->Command ==
"Fns")
10797 else if(Ptr->Command ==
"F-nshs")
10800 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
10807 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10814 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10817 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
10820 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10827 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10829 PartStr =
"Terminate at " + Ptr->LocationName;
10831 else if(Ptr->Command ==
"Frh")
10833 PartStr =
"Terminate at " + Ptr->LocationName;
10835 else if(Ptr->Command ==
"Fer")
10837 AnsiString AllowedExits;
10841 else if(Ptr->Command ==
"Fjo")
10844 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10846 else if(Ptr->Command ==
"jbo")
10849 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10851 else if(Ptr->Command ==
"fsp")
10856 else if(Ptr->Command ==
"rsp")
10861 else if(Ptr->Command ==
"cdt")
10865 else if(Ptr->Command ==
"dsc")
10871 RetStr = RetStr +
'\n' + PartStr;
10879 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
10892 + AnsiString(RptNum) +
",ControllerGetNewServiceDepartureInfo," + TDEPtr->
HeadCode);
10893 AnsiString DepTime =
"", EventTime =
"";
10894 bool CDTFlag =
false;
10896 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
10897 AnsiString TowardsLocation =
"";
10900 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
10902 TowardsLocation = AVI->LocationName;
10904 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
10913 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
10919 if(AVI->Command ==
"cdt")
10921 CDTFlag = !CDTFlag;
10924 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
10927 RetStr +=
"\nNew service splits at " + EventTime;
10931 if(AVI->Command ==
"jbo")
10934 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
10938 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
10941 RetStr +=
"\nNew service finishes and forms another new service at " + EventTime;
10945 if(AVI->Command ==
"Fjo")
10948 RetStr +=
"\nNew service finishes and joins " + AVI->OtherHeadCode +
" at " + EventTime;
10952 if(AVI->Command ==
"Frh")
10954 RetStr +=
"\nNew service finishes and remains at location.";
10958 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
10963 if(TowardsLocation !=
"")
10965 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
10969 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
10974 if(TowardsLocation !=
"")
10976 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
10980 RetStr +=
"\nNew service departs at " + DepTime;
11145 ActiveTrackElementNameMapEntry.second = 0;
11151 std::ifstream TTBLFile(FileName, std::ios_base::binary);
11154 if(TTBLFile.is_open())
11156 char *TrainTimetableString =
new char[10000];
11158 bool EndOfFile =
false;
11161 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11163 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11170 delete[] TrainTimetableString;
11174 AnsiString OneLine(TrainTimetableString);
11175 bool FinalCallFalse =
false;
11176 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
11180 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11181 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11186 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
11188 delete[] TrainTimetableString;
11192 OneLine = AnsiString(TrainTimetableString);
11198 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11200 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11210 OneLine = AnsiString(TrainTimetableString);
11212 if(OneLine.Length() > 9999)
11214 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
11216 delete[] TrainTimetableString;
11220 bool FinalCallFalse =
false;
11221 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
11225 delete[] TrainTimetableString;
11229 if(EndOfFile && (Count < 2))
11232 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
11234 delete[] TrainTimetableString;
11240 delete[] TrainTimetableString;
11245 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
11256 bool CheckLocationsExistInRailway)
11384 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
11394 if(OneLine[1] !=
'*')
11396 int SCPos = OneLine.Pos(
';');
11407 bool AllCommas =
true;
11409 for(
int x = 1; x < OneLine.Length() + 1; x++)
11411 if(OneLine[x] !=
',')
11416 if(AllCommas || (OneLine ==
""))
11431 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
11432 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
11433 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
11434 TDateTime StartTime(0);
11436 bool Warning =
false;
11463 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
11464 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
11465 double MaxBrakeRate = 0;
11466 double PowerAtRail = 0;
11467 int SignallerSpeed = 0;
11468 if(OneLine[1] ==
'*')
11474 int Pos = OneLine.Pos(
',');
11477 int SubStringLength = 20;
11478 if(OneLine.Length() < 20)
11480 SubStringLength = OneLine.Length();
11482 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
11486 TrainInfoStr = OneLine.SubString(1, Pos - 1);
11487 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
11498 TempTrainDataEntry.
HeadCode = HeadCode;
11502 if(Description !=
"")
11507 TempTrainDataEntry.
Mass = Mass;
11515 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
11518 while(NewRemainder[NewRemainder.Length()] ==
',')
11520 if(NewRemainder.Length() > 1)
11522 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
11531 if(NewRemainder ==
"")
11533 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
11538 int CommaCount = 0;
11539 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
11541 if(NewRemainder[x] ==
',')
11546 if(CommaCount == 0)
11548 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
11550 int SubStringLength = 20;
11551 if(OneLine.Length() < 20)
11553 SubStringLength = OneLine.Length();
11556 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
11557 OneLine.SubString(1, SubStringLength) +
"'....");
11562 AnsiString OneEntry =
"";
11567 bool FinishFlag =
false;
11568 bool NewTrain =
false;
11569 for(
int x = 0; x < CommaCount + 1; x++)
11571 if((CommaCount == 0) || (x < CommaCount))
11576 if(CommaCount == 0)
11578 OneEntry = NewRemainder;
11583 Pos = NewRemainder.Pos(
',');
11584 OneEntry = NewRemainder.SubString(1, Pos - 1);
11585 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
11591 RearStartOrRepeatMins = 0;
11592 FrontStartOrRepeatDigits = 0;
11593 NumberOfRepeats = 0;
11594 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11595 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11597 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11601 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11606 if(Warning && (Second ==
"Frh"))
11608 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
11612 if(Warning && (Second ==
"Fjo"))
11615 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
11621 if(NewTrain && (PowerAtRail < 1) && (Second ==
"jbo"))
11624 "': a train created without power can't 'be joined by' another train (i.e. can't include command 'jbo'), "
11625 "use command 'Fjo' (i.e. 'join' another train) instead immediately after the line containing 'Snt', and use "
11626 "command 'jbo' for the train it is to join.");
11630 if(NewTrain && (PowerAtRail < 1) && ((Second ==
"fsp") || (Second ==
"rsp")))
11633 "': a train created without power can't split.");
11637 if(NewTrain && (PowerAtRail < 1) && (Second ==
"cdt"))
11640 "': a train created without power can't change direction under timetable control.");
11649 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
11653 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
11655 if(NewRemainder[1] !=
'R')
11658 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
11664 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11668 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
11671 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
11677 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
11682 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11687 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
11690 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11706 TDateTime TempTime;
11712 ActionVectorEntry.
Warning = Warning;
11728 ActionVectorEntry.
Command = Second;
11743 else if(FormatType ==
TimeCmd)
11749 ActionVectorEntry.
Command = Second;
11757 ActionVectorEntry.
Command = Second;
11758 ActionVectorEntry.
ExitList = ExitList;
11766 ActionVectorEntry.
Command = Second;
11780 ActionVectorEntry.
Command = Second;
11791 ActionVectorEntry.
Command = Second;
11801 ActionVectorEntry.
Command = Second;
11803 if((Fourth !=
"") && ((Second ==
"fsp") || (Second ==
"rsp")))
11814 ActionVectorEntry.
Command = Second;
11823 ActionVectorEntry.
Command = Second;
11829 ActionVectorEntry.
Command = Second;
11837 ActionVectorEntry.
Command = Second;
11840 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11845 OneEntry = NewRemainder;
11850 RearStartOrRepeatMins = 0;
11851 FrontStartOrRepeatDigits = 0;
11852 NumberOfRepeats = 0;
11853 if((FinishFlag) && (OneEntry[1] !=
'R'))
11856 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
11860 if(OneEntry[1] !=
'R')
11862 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11863 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11865 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11870 if(NewTrain && (PowerAtRail < 1) && ((Second ==
"Fns") || (Second ==
"Frh-sh") || (Second ==
"Fns-sh") || (Second ==
"F-nshs")))
11873 "': a train created without power can't form a new service.");
11880 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
11887 TDateTime TempTime;
11893 ActionVectorEntry.
Warning = Warning;
11900 ActionVectorEntry.
Command = Second;
11908 ActionVectorEntry.
Command = Second;
11917 ActionVectorEntry.
Command = Second;
11926 ActionVectorEntry.
Command = Second;
11936 ActionVectorEntry.
Command = Second;
11937 ActionVectorEntry.
ExitList = ExitList;
11941 ActionVectorEntry.
Command = Second;
11943 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11948 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
11964 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11983 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
11988 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
12003 if(TimeStr.Length() < 5)
12008 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
12013 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
12018 if(TimeStr[3] !=
':')
12023 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
12028 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
12033 while(TimeStr.Length() > 5)
12035 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
12037 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
12038 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
12040 if((WholeHours + FracHour) >= 95.98334)
12045 Time = TDateTime((WholeHours + FracHour) / 24);
12052 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
12053 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
12062 TDateTime TempTime;
12064 if(OneEntry.Length() > 0)
12066 if(OneEntry[1] ==
'W')
12069 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
12073 if(OneEntry ==
"Frh")
12083 if(OneEntry.Length() < 7)
12088 int Pos = OneEntry.Pos(
';');
12096 First = OneEntry.SubString(1, 5);
12102 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
12104 if((Remainder[1] >=
'0') && (Remainder[1] <=
'9'))
12107 if(Remainder.Length() < 7)
12112 Pos = Remainder.Pos(
';');
12119 Second = Remainder.SubString(1, 5);
12125 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12138 Pos = Remainder.Pos(
';');
12141 Second = Remainder;
12142 if(Second ==
"cdt")
12167 if((Pos != 4) && (Pos != 7) && (Pos != 8))
12173 Second = Remainder.SubString(1, Pos - 1);
12175 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12177 Pos = Remainder.Pos(
';');
12184 Third = Remainder.SubString(1, Pos - 1);
12185 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12188 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
12191 int SpacePos = Third.Pos(
' ');
12197 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
12198 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
12200 if(CheckLocationsExistInRailway)
12210 if(Second ==
"Snt")
12233 if(Second ==
"Sns-sh")
12252 if(Second ==
"F-nshs")
12266 if(Second ==
"Sns-fsh")
12280 if(Second ==
"Fns-sh")
12300 if(Second ==
"pas")
12315 if(Second ==
"Fer")
12322 if(CheckLocationsExistInRailway)
12333 if(Second ==
"dsc")
12335 if(Third.Length() > 60)
12337 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters in '" + Third +
"'");
12341 for(
int x = 1; x < Third.Length() + 1; x++)
12343 if((Third[x] <
' ') || (Third[x] >
'~'))
12345 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + Third +
"'");
12361 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
12362 (Second !=
"Frh-sh"))
12374 if(Second ==
"Frh-sh")
12382 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
12386 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
12390 if((Second ==
"Sfs") || (Second ==
"Sns"))
12395 if((Fourth !=
"") && ((Second ==
"fsp") || (Second ==
"rsp")))
12412 bool ErrorFlag =
false;
12414 if((SplitDistributionString.Length() > 6 ) || (SplitDistributionString.Length() < 3))
12418 int pos = SplitDistributionString.Pos(
'-');
12425 AnsiString MassStr = SplitDistributionString.SubString(1, pos - 1);
12426 AnsiString PowerStr = SplitDistributionString.SubString(pos + 1, SplitDistributionString.Length() - pos);
12429 int x = MassStr.ToInt();
12430 int y = PowerStr.ToInt();
12431 if((x > 99) || (x < 1) || (y > 100) || (y < 0))
12436 catch(
const Exception &e)
12443 TimetableMessage(GiveMessages,
"Error in split distribution " + SplitDistributionString +
", should be 'AA-BB' where AA is the percentage mass (min 1, max 99) and BB the percentage " +
12444 "power for the new split-off train");
12464 if((LocStr[1] >=
'0') && (LocStr[1] <=
'9'))
12469 for(
int x = 1; x < LocStr.Length() + 1; x++)
12471 if(LocStr[x] <
' ')
12476 if(LocStr[x] >
'z')
12483 if(CheckLocationsExistInRailway)
12488 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
12489 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
12490 "that includes a continuation will not be valid.");
12508 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
12511 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
12516 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
12518 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
12520 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
12526 for(
int x = 3; x >= 0; x--)
12528 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
12529 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
12531 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
12547 AnsiString CurrentID =
"";
12549 if(IDSet.Length() == 0)
12551 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
12555 for(
int x = 1; x <= IDSet.Length(); x++)
12558 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
12560 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
12582 int Pos = IDSet.Pos(
' ');
12593 CurrentID = IDSet.SubString(1, Pos - 1);
12594 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
12606 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
12613 if(!ExitList.empty())
12615 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
12617 if(*ELIT == VecPos)
12619 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
12626 ExitList.push_back(VecPos);
12636 Pos = IDSet.Pos(
' ');
12643 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
12650 AnsiString Remainder =
"";
12651 int SemiColonCount = 0;
12653 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
12655 if(TrainInfoStr[x] ==
';')
12660 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
12662 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
12663 "'. Should be headcode + optional description for a continuing service;" +
12664 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
12668 if(SemiColonCount == 0)
12670 HeadCode = TrainInfoStr;
12679 if(SemiColonCount == 1)
12681 Pos = TrainInfoStr.Pos(
';');
12682 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12683 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12689 if(Description ==
"")
12691 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12695 if(Description.Length() > 60)
12697 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12701 for(
int x = 1; x < Description.Length() + 1; x++)
12703 if((Description[x] <
' ') || (Description[x] >
'~'))
12705 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12714 Pos = TrainInfoStr.Pos(
';');
12715 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12716 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12722 Pos = Remainder.Pos(
';');
12723 Description = Remainder.SubString(1, Pos - 1);
12724 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12725 if(Description ==
"")
12727 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12731 if(Description.Length() > 60)
12733 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12737 for(
int x = 1; x < Description.Length() + 1; x++)
12739 if((Description[x] <
' ') || (Description[x] > 126))
12741 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12746 Pos = Remainder.Pos(
';');
12747 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
12749 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12750 if(StartSpeedStr ==
"")
12752 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
12756 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
12758 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
12760 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
12765 StartSpeed = StartSpeedStr.ToInt();
12771 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12775 Pos = Remainder.Pos(
';');
12776 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
12778 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12779 if(MaxRunningSpeedStr ==
"")
12781 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
12785 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
12787 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
12789 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
12794 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
12800 TimetableMessage(GiveMessages,
"Train maximum running speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12804 if(MaxRunningSpeed < 10)
12807 MaxRunningSpeed = 10;
12810 TimetableMessage(GiveMessages,
"Train maximum running speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12814 Pos = Remainder.Pos(
';');
12815 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
12817 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12820 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
12824 for(
int x = 1; x < MassStr.Length() + 1; x++)
12826 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
12828 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
12833 Mass = MassStr.ToInt() * 1000;
12839 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
12845 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
12849 Pos = Remainder.Pos(
';');
12850 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
12852 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12853 if(MaxBrakeForceStr ==
"")
12855 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
12859 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
12861 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
12863 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
12868 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
12871 if((MaxBrakeForce / Mass) > 1)
12873 MaxBrakeForce = Mass;
12876 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
12880 if((MaxBrakeForce / Mass) < 0.01)
12882 MaxBrakeForce = Mass * 0.01;
12885 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
12890 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
12892 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
12894 if(SemiColonCount == 6)
12896 GrossPowerStr = Remainder;
12897 SignallerSpeedStr =
"30";
12901 Pos = Remainder.Pos(
';');
12902 GrossPowerStr = Remainder.SubString(1, Pos - 1);
12903 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12906 if(GrossPowerStr ==
"")
12908 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
12912 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
12914 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
12916 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
12922 double GrossPower = GrossPowerStr.ToInt() * 1000;
12929 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
12933 else if(GrossPower == 0)
12938 else if((GrossPower > 0) && (GrossPower < 10000))
12941 GrossPower = 10000;
12943 PowerAtRail = GrossPower * 0.8;
12947 if(SignallerSpeedStr ==
"")
12949 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
12953 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
12955 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
12957 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
12962 SignallerSpeed = SignallerSpeedStr.ToInt();
12968 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12972 if(SignallerSpeed < 10)
12975 SignallerSpeed = 10;
12978 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12996 if(OneEntry.Length() < 7)
12998 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13002 int SemiColonCount = 0;
13004 for(
int x = 1; x < OneEntry.Length() + 1; x++)
13006 if(OneEntry[x] ==
';')
13011 if(SemiColonCount != 3)
13013 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13017 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
13019 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13023 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
13028 Pos = Remainder.Pos(
';');
13029 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
13031 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13032 if(MinutesStr ==
"")
13034 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
13038 if(MinutesStr.Length() > 3)
13041 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
13045 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
13047 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
13049 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
13054 RearStartOrRepeatMins = MinutesStr.ToInt();
13055 if(RearStartOrRepeatMins == 0)
13057 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
13061 Pos = Remainder.Pos(
';');
13062 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
13064 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13065 if(DigitsStr ==
"")
13067 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
13071 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
13073 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
13075 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
13080 if(DigitsStr.Length() > 2)
13082 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
13086 FrontStartOrRepeatDigits = DigitsStr.ToInt();
13100 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
13104 AnsiString NumberStr = Remainder;
13106 if(NumberStr ==
"")
13108 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
13112 if(NumberStr.Length() > 4)
13115 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
13119 for(
int x = 1; x < NumberStr.Length() + 1; x++)
13121 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
13124 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
13129 NumberOfRepeats = NumberStr.ToInt();
13130 if(NumberOfRepeats == 0)
13132 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
13304 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
13325 TwoLocationFlag =
false;
13331 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
13345 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
13361 "Error in timetable - a signaller controlled service can have no more than one item (a repeat) after the start event, see: " +
13373 "Error in timetable - a signaller controlled service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
13399 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
13412 SecondPassMessage(GiveMessages,
"Error in timetable - only 'Frh' or 'Fjo' finish events are permitted immediately after an 'Sns' or 'Sfs' entry for: " +
13419 if((AVEntry0.
Command ==
"Snt-sh") || (AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13425 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event can't immediately follow an 'Snt-sh', 'Sns-sh' or 'Sns-fsh' event for: " + TDEntry.
HeadCode);
13435 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13440 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
13450 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13455 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
13465 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13476 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
13486 SecondPassMessage(GiveMessages,
"Error in timetable - the event immediately before the repeat must be a finish for: " + TDEntry.
HeadCode);
13498 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13505 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
13514 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " + TDEntry.
HeadCode);
13533 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
13535 AnsiString LocationName =
"";
13549 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
13550 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13559 if(AVEntry0.
Command ==
"Snt-sh")
13573 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
13589 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh', 'Snt-fsh' or 'Sns-fsh' followed by an illegal event for: " +
13590 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13602 bool FoundFlag =
false;
13606 if((AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13608 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13620 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sns-sh' or 'Sns-fsh' event for: " + TDEntry.
HeadCode);
13633 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13658 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13680 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13702 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13727 bool LocFoundFlag, FnsFoundFlag;
13731 LocFoundFlag =
false;
13732 FnsFoundFlag =
false;
13733 for(
int y =
TrainDataVector.at(x).ActionVector.size() - 1; y >= 0; y--)
13738 FnsFoundFlag =
true;
13747 LocFoundFlag =
true;
13758 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' finish must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13764 if(FnsFoundFlag && !LocFoundFlag)
13766 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' finish must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13779 if(AVEntry0.
Command ==
"Sns")
13791 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sns' event for: " + TDEntry.
HeadCode);
13799 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' entry is followed by an illegal event for: " + TDEntry.
HeadCode +
13800 ". The event isn't valid for a stationary train.");
13808 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' entry is followed by an illegal event for: " + TDEntry.
HeadCode);
13815 TDateTime SnsEventTime = AVEntry0.
EventTime;
13818 bool BreakFlag =
false;
13821 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
13826 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SnsServiceRef)
13847 if(AVEntry0.
Command ==
"Sfs")
13849 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13857 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' action must be followed by a departure and arrival before another split, see " +
TrainDataVector.at(x).ServiceReference);
13869 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13874 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
13894 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13901 SecondPassMessage(GiveMessages,
"Error in timetable - an 'fsp' or 'rsp' event must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13916 if(AVEntry0.
Command ==
"Sfs")
13928 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sfs' event for: " + TDEntry.
HeadCode);
13936 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' entry is followed by an illegal event for: " + TDEntry.
HeadCode +
13937 ". The event isn't valid for a stationary train.");
13945 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' entry is followed by an illegal event for: " + TDEntry.
HeadCode);
13952 TDateTime SfsEventTime = AVEntry0.
EventTime;
13954 bool BreakFlag =
false;
13957 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
13962 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SfsServiceRef)
13982 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13987 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
14008 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14015 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"' must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
14023 "Please make sure that the finish event of the service that links to this event is preceded by an "
14024 "event at the same location that has an identified location name, normally an arrival.");
14031 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
14044 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14054 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish entry for: " + TDEntry.
HeadCode);
14061 if(AVEntry.
Command ==
"F-nshs")
14066 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
14094 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
14095 ". The event isn't valid for a stationary train.");
14105 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
14113 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
14114 ". The event isn't valid for a stationary train.");
14132 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
14133 ". The event isn't valid for a stationary train.");
14151 SecondPassMessage(GiveMessages,
"Error in timetable - a 'dsc' is followed by an illegal event for: " + TDEntry.
HeadCode +
14152 ". The event isn't valid for a stationary train.");
14162 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
14170 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
14171 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
14189 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
14190 ". The event isn't valid for a moving train.");
14212 bool LastEntryIsAnArrival =
false;
14219 LastEntryIsAnArrival =
false;
14220 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14227 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14229 if(LastEntryIsAnArrival)
14233 LastEntryIsAnArrival =
false;
14239 LastEntryIsAnArrival =
true;
14246 LastEntryIsAnArrival =
true;
14247 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14254 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14256 if(LastEntryIsAnArrival)
14260 LastEntryIsAnArrival =
false;
14266 LastEntryIsAnArrival =
true;
14276 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14284 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
14292 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
14293 ". The event isn't valid for a stationary train.");
14304 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
14312 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
14313 ". The event isn't valid for a moving train.");
14327 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14334 throw Exception(
"Timetable error, TimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
14338 throw Exception(
"Timetable error, TimeLoc entry has neither arrival nor departure time set for " + TDEntry.
HeadCode);
14345 throw Exception(
"Timetable error, TimeTimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
14349 throw Exception(
"Timetable error, TimeTimeLoc entry has either arrival or departure time not set for " + TDEntry.
HeadCode);
14358 throw Exception(
"Timetable error, Cmd or PassTime entry has EventTime not set for " + TDEntry.
HeadCode);
14362 throw Exception(
"Timetable error, Cmd or PassTime entry has either arrival or departure time set for " + TDEntry.
HeadCode);
14369 throw Exception(
"Timetable error, Repeat entry has a time set for " + TDEntry.
HeadCode);
14380 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14395 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
14403 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
14418 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14430 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14442 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
14443 ", may be before timetable start time");
14454 AnsiString LastLocationName =
"";
14458 bool LastEntryIsAnArrival =
false;
14463 LastEntryIsAnArrival =
false;
14464 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14465 if(LastLocationName !=
"")
14467 throw Exception(
"Timetable error, moving Snt entry has LocationName set for " + TDEntry.
HeadCode);
14469 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
14482 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14494 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14507 TwoLocationFlag =
true;
14512 LastEntryIsAnArrival =
false;
14516 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
14519 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
14524 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
14527 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
14533 LastEntryIsAnArrival = !LastEntryIsAnArrival;
14539 LastEntryIsAnArrival =
true;
14540 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14541 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14553 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14565 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14578 TwoLocationFlag =
true;
14583 LastEntryIsAnArrival =
false;
14587 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
14590 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
14598 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
14605 LastEntryIsAnArrival = !LastEntryIsAnArrival;
14613 AnsiString LocationNameToBeChecked =
"";
14618 unsigned int y = 0;
14632 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
14633 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
14651 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
14660 TwoLocationFlag =
true;
14671 if(TwoLocationFlag)
14681 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14686 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat entry doesn't have a location name set for " + TDEntry.
HeadCode);
14688 AnsiString LocName =
"";
14694 throw Exception(
"Error, 'Snt' entry at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
14701 throw Exception(
"Error, 'Snt' unlocated entry has a location name set for " + TDEntry.
HeadCode);
14724 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14749 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14771 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14793 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14812 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14815 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
14830 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14835 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
14839 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
14843 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
14847 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
14886 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14888 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
14894 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
14907 int IncMinutes = 0;
14917 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14923 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
14929 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
14934 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
14940 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
14945 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
14958 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14984 (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"F-nshs"));
14992 if(HeadCode.Length() > 4)
14994 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
15005 int ForwardCount = 0;
15006 int ReverseCount = 0;
15008 if(MainHeadCode == SecondHeadCode)
15010 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
15019 if(TDEntry.
HeadCode == MainHeadCode)
15021 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15036 if(ForwardCount == 0)
15039 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
15041 if(ForwardCount > 2)
15044 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
15045 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
15054 if(TDEntry.
HeadCode == SecondHeadCode)
15056 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15071 if(ReverseCount == 0)
15073 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
15078 if(ReverseCount > 2)
15081 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
15082 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
15087 if(ForwardCount != ReverseCount)
15089 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
15090 " than the other way round");
15121 int ForwardCount = 0;
15122 int ReverseCount = 0;
15123 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
15132 if(TDEntry.
HeadCode == MainHeadCode)
15134 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15137 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15142 ForwardEntryPtr = &AVEntry;
15144 ForwardTDVectorNumber = x;
15147 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
15148 (AVEntry.
Command ==
"Frh-sh")))
15153 ForwardEntryPtr = &AVEntry;
15155 ForwardTDVectorNumber = x;
15161 if(ForwardCount == 0)
15164 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
15166 if(ForwardCount > 1)
15168 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
15178 if(TDEntry.
HeadCode == OtherHeadCode)
15180 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15183 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15189 ReverseEntryPtr = &AVEntry;
15190 ReverseTDVectorNumber = x;
15193 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
15199 ReverseEntryPtr = &AVEntry;
15200 ReverseTDVectorNumber = x;
15207 if(ReverseCount == 0)
15209 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
15214 if(ReverseCount > 1)
15216 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
15223 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
15224 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
15225 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
15226 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
15230 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
15237 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
15242 if(SetDataAndCheckLocations)
15244 if(ForwardEntryPtr->LocationName ==
"")
15246 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
15247 ". One or other service does not have a location set");
15254 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
15255 ". One or other service does not have a location set");
15260 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
15262 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
15263 " is at a different location to the referencing train " + MainHeadCode);
15272 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
15274 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
15275 " has a different event time to the referencing train " + MainHeadCode);
15283 if(ForwardShuttleStart && ReverseShuttleFinish)
15288 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
15289 " first repeat restart time not consistent with finish service " + OtherHeadCode);
15295 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
15298 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15300 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
15301 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15307 if(ReverseEntryPtr->
Command ==
"Fjo")
15310 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15312 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
15313 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15319 if(ReverseEntryPtr->
Command ==
"Fns")
15322 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15324 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
15325 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15331 if(ForwardEntryPtr->Command ==
"Sfs")
15333 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
15336 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
15343 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
15345 if(ReverseEntryPtr->
Command !=
"Sfs")
15347 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
15355 if(SetDataAndCheckLocations)
15359 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
15366 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
15373 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
15378 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15390 if(ForwardEntryPtr->Command ==
"Sns")
15392 if(ReverseEntryPtr->
Command !=
"Fns")
15394 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
15395 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
15401 if(ForwardEntryPtr->Command ==
"Fns")
15403 if(ReverseEntryPtr->
Command !=
"Sns")
15405 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
15406 " and forms a new service with headcode " + OtherHeadCode);
15413 if(SetDataAndCheckLocations)
15415 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15427 if(ForwardEntryPtr->Command ==
"jbo")
15429 if(ReverseEntryPtr->
Command !=
"Fjo")
15431 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
15432 " and is joined by a train with headcode " + OtherHeadCode);
15438 if(ForwardEntryPtr->Command ==
"Fjo")
15440 if(ReverseEntryPtr->
Command !=
"jbo")
15442 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
15443 " and joins a train with headcode " + OtherHeadCode);
15450 if(SetDataAndCheckLocations)
15452 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15468 if(ForwardShuttleStart)
15471 if(!ReverseShuttleFinish)
15474 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
15475 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
15481 if(ReverseShuttleStart)
15484 if(!ForwardShuttleFinish)
15487 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
15488 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
15495 if(SetDataAndCheckLocations)
15497 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15510 bool MainRepeat =
false, OtherRepeat =
false;
15520 OtherRepeat =
true;
15523 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
15525 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
15526 " and the associated train with headcode " + OtherHeadCode);
15531 if(MainRepeat && OtherRepeat)
15537 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
15538 " and the associated train with headcode " + OtherHeadCode);
15560 while(Input[1] ==
' ')
15562 if(Input.Length() > 1)
15564 Input = Input.SubString(2, Input.Length() - 1);
15578 while(Input[Input.Length()] ==
' ')
15580 if(Input.Length() > 1)
15582 Input = Input.SubString(1, Input.Length() - 1);
15592 AnsiString Output =
"";
15593 bool DelimiterFound =
false;
15595 for(
int x = 1; x < Input.Length() + 1; x++)
15599 if(Input[x] ==
' ')
15604 if((Input[x] !=
',') && (Input[x] !=
';'))
15606 DelimiterFound =
false;
15607 Output = Output + Input[x];
15611 DelimiterFound =
true;
15612 Output = Output + Input[x];
15624 DelimiterFound =
false;
15625 for(
int x = Input.Length(); x > 0; x--)
15629 if(Input[x] ==
' ')
15634 if((Input[x] !=
',') && (Input[x] !=
';'))
15636 DelimiterFound =
false;
15637 Output = AnsiString(Input[x]) + Output;
15641 DelimiterFound =
true;
15642 Output = AnsiString(Input[x]) + Output;
15667 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
15669 throw Exception(
"Error, first entry not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
15681 LocationName = LocRear;
15685 LocationName = LocFront;
15687 if(LocationName ==
"")
15708 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
15749 int RearPosition = 0, FrontPosition = 0, RearExitPos = 0;
15752 if(RearPosition < 0)
15759 if(FrontPosition < 0)
15770 for(
int x = 0; x < 4; x++)
15772 if(RearTrackElement.
Conn[x] == FrontPosition)
15787 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
15794 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
15800 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
15805 if((RearType ==
Points) && (RearExitPos == 3))
15807 TimetableMessage(GiveMessages,
"Front of train attempting to start on element connected to diverging points at: " + RearElementStr);
15813 TimetableMessage(GiveMessages,
"Rear of train attempting to start on element connected to diverging points at: " + FrontElementStr);
15828 AnsiString(RearExitPos));
15839 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
15841 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
15844 AnsiString RearName, FrontName;
15860 FrontName = FrontTrackElement.
ElementID;
15863 int LockedVectorNumber;
16033 "," + AnsiString(IncDigits));
16036 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
16041 return(BaseHeadCode);
16043 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
16044 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
16046 while(NextRepeatDigits >= 100)
16048 NextRepeatDigits -= 100;
16050 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
16052 if(NextRepeatDigitsStr.Length() < 2)
16054 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
16056 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
16059 return(NextRepeatHeadCode);
16067 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
16068 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
16070 return(NextRepeatTime);
16079 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
16080 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16081 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16082 int RepeatSecs = RepeatMinutes * 60;
16084 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
16118 NonRepeatingHeadCode);
16119 int ForwardCount = 0;
16120 int ReverseCount = 0;
16121 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
16131 if(TDEntry.
HeadCode == MainHeadCode)
16133 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16139 ForwardEntryPtr = &AVEntry;
16141 ForwardTDVectorNumber = x;
16146 if(ForwardCount == 0)
16149 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
16151 if(ForwardCount > 1)
16153 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
16163 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
16165 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16172 ReverseEntryPtr = &AVEntry;
16173 ReverseTDVectorNumber = x;
16179 if(ReverseCount == 0)
16181 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
16186 if(ReverseCount > 1)
16188 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
16189 NonRepeatingHeadCode);
16194 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
16196 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
16201 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
16203 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
16208 if(SetDataAndCheckLocations)
16210 if(ForwardEntryPtr->LocationName ==
"")
16212 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
16213 ". One or other service does not have a location set");
16220 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
16221 ". One or other service does not have a location set");
16226 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
16228 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
16229 " is at a different location to the referencing train " + MainHeadCode);
16235 if(ForwardEntryPtr->Command ==
"F-nshs")
16238 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
16240 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
16241 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
16247 if(ForwardEntryPtr->Command ==
"Fns-sh")
16251 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
16253 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
16254 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
16260 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
16263 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
16265 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
16266 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
16284 if(ForwardEntryPtr->Command ==
"Sns-sh")
16286 if(ReverseEntryPtr->
Command !=
"F-nshs")
16288 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
16289 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
16295 if(ForwardEntryPtr->Command ==
"F-nshs")
16297 if(ReverseEntryPtr->
Command !=
"Sns-sh")
16299 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
16300 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
16307 if(SetDataAndCheckLocations)
16309 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
16321 if(ForwardEntryPtr->Command ==
"Sns-fsh")
16323 if(ReverseEntryPtr->
Command !=
"Fns-sh")
16326 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
16327 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
16333 if(ForwardEntryPtr->Command ==
"Fns-sh")
16335 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
16338 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
16339 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
16346 if(SetDataAndCheckLocations)
16348 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
16372 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
16373 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16374 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16375 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
16377 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
16401 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
16404 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
16405 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16407 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16409 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16414 while(LastActionCommand ==
"Fns")
16416 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
16417 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16418 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16421 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
16422 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16429 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
16432 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
16433 ". The linking of two or more shuttles is not permitted.");
16453 ShowMessage(Message);
16471 ShowMessage(Message);
16480 int Mins = Input, Hrs = 0;
16486 AnsiString AnsiMins = AnsiString(Mins);
16487 if(AnsiMins.Length() == 1)
16489 AnsiMins =
"0" + AnsiMins;
16491 AnsiString AnsiHrs = AnsiString(Hrs);
16492 if(AnsiHrs.Length() == 1)
16494 AnsiHrs =
"0" + AnsiHrs;
16497 return(AnsiHrs +
':' + AnsiMins);
16537 AnsiString(ActionEventType) +
"," + LocationID);
16538 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
16543 Prefix =
" ERROR: ";
16546 Prefix =
" HELD: ";
16547 ErrorLog =
" can't enter railway, train obstructing entry position ";
16548 WarningStr =
" can't enter railway, train obstructing entry position ";
16553 Prefix =
" HELD: ";
16554 ErrorLog =
" can't enter railway, route set against it at entry position ";
16555 WarningStr =
" can't enter railway, route set against it at entry position ";
16560 Prefix =
" HELD: ";
16561 ErrorLog =
" can't be created, train obstructing ";
16562 WarningStr =
" can't be created, train obstructing ";
16567 Prefix =
" HELD: ";
16568 ErrorLog =
" can't be created on a locked route at ";
16569 WarningStr =
" can't be created on a locked route at ";
16574 Prefix =
" HELD: ";
16575 ErrorLog =
" can't enter on a locked route at ";
16576 WarningStr =
" can't enter on a locked route at ";
16581 Prefix =
" HELD: ";
16582 ErrorLog =
" can't be created, diverging points at ";
16583 WarningStr =
" can't be created, diverging points at ";
16588 ErrorLog =
" left railway unexpectedly at ";
16593 ErrorLog =
" left railway at an incorrect exit at ";
16598 ErrorLog =
" failed to split - location too short at ";
16599 WarningStr =
" failed to split, location too short at ";
16604 Prefix =
" HELD: ";
16605 ErrorLog =
" unable to split - other train obstructing at ";
16606 WarningStr =
" unable to split - other train obstructing at ";
16611 ErrorLog =
" stopped at buffers unexpectedly at position ";
16615 ErrorLog =
" failed to stop at ";
16620 ErrorLog =
" failed to split at ";
16625 ErrorLog =
" failed to be joined by other train at ";
16630 ErrorLog =
" failed to change its description at ";
16635 ErrorLog =
" failed to join other train at ";
16640 ErrorLog =
" failed to terminate at ";
16645 ErrorLog =
" failed to form new service at ";
16650 ErrorLog =
" failed to exit railway ";
16655 ErrorLog =
" failed to change direction at ";
16660 ErrorLog =
" failed to pass ";
16665 ErrorLog =
" facing buffers and unable to start at ";
16669 ErrorLog =
" DERAILED at position ";
16670 Prefix =
" DERAILMENT: ";
16675 ErrorLog =
" CRASHED INTO BUFFERS at ";
16676 Prefix =
" CRASH: ";
16681 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
16682 Prefix =
" CRASH: ";
16687 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
16688 Prefix =
" CRASH: ";
16692 else if(ActionEventType ==
FailSPAD)
16694 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
16695 Prefix =
" SPAD: ";
16700 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
16701 Prefix =
" SPAD RISK: ";
16706 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
16710 Prefix =
" WARNING: ";
16711 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
16712 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
16717 Prefix =
" WARNING: ";
16718 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
16719 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
16757 std::ofstream OutFile(
"TrainData.csv");
16761 ShowMessage(
"Output file TrainData.csv failed to open");
16768 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
16773 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
16774 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
16775 "RepeatNumber" <<
'\n' <<
'\n';
16776 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16779 AnsiString TimetableEntryTypeStr;
16785 TimetableEntryTypeStr =
"NoFormat";
16791 TimetableEntryTypeStr =
"TimeLoc";
16797 TimetableEntryTypeStr =
"TimeTimeLoc";
16803 TimetableEntryTypeStr =
"TimeCmd";
16809 TimetableEntryTypeStr =
"StartNew";
16815 TimetableEntryTypeStr =
"TimeCmdHeadCode";
16821 TimetableEntryTypeStr =
"FinRemHere";
16827 TimetableEntryTypeStr =
"FNSShuttle";
16833 TimetableEntryTypeStr =
"SNTShuttle";
16839 TimetableEntryTypeStr =
"SNSShuttle";
16845 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
16851 TimetableEntryTypeStr =
"FSHNewService";
16857 TimetableEntryTypeStr =
"Repeat";
16863 TimetableEntryTypeStr =
"Default";
16874 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
16875 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
16878 AnsiString RunningEntryStr;
16884 RunningEntryStr =
"NotStarted";
16890 RunningEntryStr =
"Running";
16896 RunningEntryStr =
"Exited";
16900 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
16917 ShowMessage(Message);
16918 BaseTime = TDateTime::CurrentDateTime();
16932 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
16945 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
16947 for(
int x = 0; x < NumberOfTrains; x++)
16949 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
16969 int NumberOfTrains;
16976 for(
int x = 0; x < NumberOfTrains; x++)
17013 for(
int x = 0; x < LockedRouteVectorSize; x++)
17020 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
17031 int LockedRouteVectorSize;
17038 for(
int x = 0; x < LockedRouteVectorSize; x++)
17096 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17104 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
17115 int ContinuationAutoSigVectorSize;
17122 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17192 if(AVFirstEntry.
Command ==
"Snt")
17216 CTEMMP.second = CTEEntry;
17223 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
17231 CTEMMP.second = CTEEntry;
17252 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17269 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
17271 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
17282 AnsiString RetStr =
"", PartStr =
"";
17397 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17401 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
17403 AnsiString ShortTTName =
"";
17405 for(
int x = TTFileName.Length(); x > 0; x--)
17407 if(TTFileName[x] ==
'\\')
17409 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
17414 ShowMessage(
"Creates two timetables named " + ShortTTName +
17415 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
17417 Screen->Cursor = TCursor(-11);
17419 AnsiString FormatNoDPStr =
"#######0";
17420 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
17423 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
17430 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
17432 if(TrainDataEntry.
Mass > 0)
17434 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
17438 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
17442 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
17446 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
17448 FirstHeadCode = TrainDataEntry.
HeadCode;
17449 int IncDigits = 0, IncMinutes = 0;
17451 if(!ActionVector.empty())
17453 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
17455 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
17456 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
17464 if((TrainDataEntry.
Description !=
"") && (MassStr !=
""))
17466 OneTTLine.
Header = TrainDataEntry.
Description + MassStr + PowerStr + BrakeStr + MaxSpeedStr;
17474 for(
unsigned int z = 0; z < ActionVector.size(); z++)
17479 AnsiString PartStr =
"", TimeStr =
"";
17496 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
17500 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
17510 PartStr =
"Enters at " + LocName;
17523 PartStr =
"Created at " + LocName;
17537 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
17542 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
17548 else if(ActionVectorEntry.
Command ==
"Sfs")
17550 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
17554 else if(ActionVectorEntry.
Command ==
"Sns")
17556 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17564 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17570 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
17578 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17581 AnsiString FirstHeadCode = TDE->
HeadCode;
17585 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
17597 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
17599 OneTTEntry.
Action = PartStr;
17600 OneTTEntry.
Time = TimeStr;
17602 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
17607 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
17613 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
17618 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
17626 else if(ActionVectorEntry.
Command ==
"jbo")
17628 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
17632 else if(ActionVectorEntry.
Command ==
"fsp")
17636 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
17640 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
17645 else if(ActionVectorEntry.
Command ==
"rsp")
17649 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
17653 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
17658 else if(ActionVectorEntry.
Command ==
"cdt")
17660 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
17663 else if(ActionVectorEntry.
Command ==
"dsc")
17665 PartStr =
"Changes description at " + ActionVectorEntry.
LocationName;
17671 if(ActionVectorEntry.
Command ==
"Fns")
17673 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17677 else if(ActionVectorEntry.
Command ==
"F-nshs")
17679 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17685 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
17692 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17698 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17705 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
17710 else if(ActionVectorEntry.
Command ==
"Frh")
17712 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
17717 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
17721 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
17731 else if(ActionVectorEntry.
Command ==
"Fer")
17733 AnsiString AllowedExits;
17737 else if(ActionVectorEntry.
Command ==
"Fjo")
17739 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
17748 OneTTEntry.
Action = PartStr;
17749 OneTTEntry.
Time = TimeStr;
17756 AllTTTrains->push_back(OneTTLine);
17760 std::ofstream TTFile(TTFileName.c_str());
17764 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
17765 delete AllTTTrains;
17800 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
17801 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
17803 TTFile << AllTTTrains->at(x).Header.c_str();
17806 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17808 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
17810 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
17814 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
17817 TTFile <<
'\n' <<
'\n';
17819 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
17821 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
17822 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17824 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
17826 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
17830 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
17835 TTFile <<
'\n' <<
'\n';
17840 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17842 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
17844 std::ofstream TTFile2(TTFileName2.c_str());
17848 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
17849 delete AllTTTrains;
17853 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
17854 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
17855 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
17857 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
17862 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
17863 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
17865 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17867 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
17869 bool GiveMessagesFalse =
false;
17870 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
17871 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
17872 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
17877 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
17878 TimeString = TimeString.SubString(9, 5);
17879 ActionString +=
" " + OtherHeadCode;
17881 if(TimeString.SubString(1, 7) ==
"End at ")
17884 TimeString = TimeString.SubString(8, 5);
17886 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
17887 AnsiMultiMapEntry.first = TimeString;
17888 AnsiMultiMapEntry.second = OneLine;
17889 TAMM->insert(AnsiMultiMapEntry);
17894 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
17896 TTFile2 << (AMMIT->second).c_str();
17898 delete AllTTTrains;
17907 bool AtLocChecked,
bool DirChecked,
int ArrRange,
int DepRange)
17911 bool AnalysisError =
false;
17912 AnsiString SequenceLog =
"SequenceLog\n";
17955 TTrainDataVector::iterator TDVIt, TDVCopyIt;
17957 int IteratorNumber = 0;
17958 AnsiString AnsiSuffix =
"";
17965 if(TDVCopyIt->HeadCode == TDVIt->HeadCode)
17968 AnsiSuffix = AnsiString(Suffix);
17969 TDVCopyIt->ServiceReference = TDVIt->HeadCode +
"/" + AnsiSuffix;
17970 TDVCopyIt->HeadCode = TDVIt->HeadCode +
"/" + AnsiSuffix;
17976 int Increment = 0, SlashPos;
17978 AnsiString LinkedHeadCode;
17982 for(AVEIt = TDVCopyIt->ActionVector.begin(); AVEIt != TDVCopyIt->ActionVector.end(); AVEIt++)
17984 if(AVEIt->LinkedTrainEntryPtr != NULL)
17993 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
17995 if(LinkedHeadCode[x] ==
'/')
17997 SlashPos = LinkedHeadCode.Length() - x + 1;
18000 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
18001 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
18002 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
18008 AVEIt->OtherHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
18012 AVEIt->OtherHeadCode =
"";
18014 if(AVEIt->NonRepeatingShuttleLinkEntryPtr != NULL)
18016 Increment = AVEIt->NonRepeatingShuttleLinkEntryPtr - &
TrainDataVector.at(0);
18020 LinkedHeadCode = (*AVEIt->NonRepeatingShuttleLinkEntryPtr).
ServiceReference;
18023 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
18025 if(LinkedHeadCode[x] ==
'/')
18027 SlashPos = LinkedHeadCode.Length() - x + 1;
18030 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
18031 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
18032 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
18038 AVEIt->NonRepeatingShuttleLinkHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
18042 AVEIt->NonRepeatingShuttleLinkHeadCode =
"";
18047 SequenceLog +=
"1\n";
18050 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
18056 ServiceCallingLocsList.clear();
18057 if(ActionVector.empty())
18061 if(ActionVector.at(0).SignallerControl)
18065 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18083 int HLoc = TE.
HLoc;
18084 int VLoc = TE.
VLoc;
18085 AnsiString HString;
18086 AnsiString VString;
18089 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18093 HString = AnsiString(HLoc);
18097 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18101 VString = AnsiString(VLoc);
18103 ServiceCallingLocsList.push_back(HString +
'-' + VString);
18126 else if(AVE.
Command ==
"cdt")
18139 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
18148 ServiceCallingLocsList.push_back(LName);
18152 int HLoc = TE.
HLoc;
18153 int VLoc = TE.
VLoc;
18154 AnsiString HString;
18155 AnsiString VString;
18158 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18162 HString = AnsiString(HLoc);
18166 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18170 VString = AnsiString(VLoc);
18172 ServiceCallingLocsList.push_back(HString +
'-' + VString);
18176 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
18180 SequenceLog +=
"2\n";
18209 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
18215 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
18216 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
18217 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
18219 SequenceLog +=
"3\n";
18226 TDateTime LastTDTime;
18227 int IncMinutes = 0;
18229 if(ActionVector.empty())
18233 if(ActionVector.at(0).SignallerControl)
18237 if(AVLast->FormatType ==
Repeat)
18239 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18247 if(AVLast->ArrivalTime != TDateTime(-1))
18249 LastTDTime = AVLast->ArrivalTime;
18251 else if(AVLast->EventTime != TDateTime(-1))
18253 LastTDTime = AVLast->EventTime;
18272 SequenceLog +=
"4\n";
18309 int IncMinutes = 0;
18311 if(ActionVector.empty())
18315 if(ActionVector.at(0).SignallerControl)
18319 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
18321 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18323 for(
int y = 0; y < NumTrains; y++)
18337 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18352 LocServiceTimesVector.push_back(TLSTEntry);
18355 AnsiString IncTime =
"", FoundStopTime =
"";
18356 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18358 if(ActionVector.at(a).FormatType ==
TimeLoc)
18369 if(FoundStopTime ==
"")
18371 throw Exception(
"Failure to determine FoundStopTime for located Snt");
18373 int WhileCount = 0;
18382 if(IncTime >= FoundStopTime)
18386 LocServiceTimesVector.push_back(TLSTEntry);
18387 if(WhileCount > 2000)
18389 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
18402 int HLoc = TE.
HLoc;
18403 int VLoc = TE.
VLoc;
18404 AnsiString HString;
18405 AnsiString VString;
18408 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18412 HString = AnsiString(HLoc);
18416 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18420 VString = AnsiString(VLoc);
18422 TLSTEntry.
Location = HString +
'-' + VString;
18426 LocServiceTimesVector.push_back(TLSTEntry);
18434 LocServiceTimesVector.push_back(TLSTEntry);
18436 AnsiString IncTime =
"", FoundStopTime =
"";
18437 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18439 if(ActionVector.at(a).FormatType ==
TimeLoc)
18450 if(FoundStopTime ==
"")
18452 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18454 int WhileCount = 0;
18463 if(IncTime >= FoundStopTime)
18467 LocServiceTimesVector.push_back(TLSTEntry);
18468 if(WhileCount > 2000)
18470 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
18480 bool SkipAddingMinutes =
false;
18483 LocServiceTimesVector.push_back(TLSTEntry);
18485 AnsiString IncTime =
"", FoundStopTime =
"";
18486 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18488 if(ActionVector.at(a).FormatType ==
TimeLoc)
18496 if((a <= (z + 2)) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr != NULL) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr != NULL)))
18500 LocServiceTimesVector.pop_back();
18501 SkipAddingMinutes =
true;
18506 if(FoundStopTime ==
"")
18508 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18510 if(!SkipAddingMinutes)
18512 int WhileCount = 0;
18521 if(IncTime >= FoundStopTime)
18525 LocServiceTimesVector.push_back(TLSTEntry);
18526 if(WhileCount > 2000)
18528 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
18537 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
18539 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
18541 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
18542 LocServiceTimesVector.pop_back();
18543 LocServiceTimesVector.push_back(TLSTEntry);
18548 LocServiceTimesVector.push_back(TLSTEntry);
18554 LocServiceTimesVector.push_back(TLSTEntry);
18573 LocServiceTimesVector.push_back(TLSTEntry);
18577 AnsiString TempDepTime = TLSTEntry.
DepTime;
18579 LocServiceTimesVector.push_back(TLSTEntry);
18581 while(TLSTEntry.
AtLocTime < TempDepTime)
18586 TLSTEntry.
DepTime = TempDepTime;
18587 LocServiceTimesVector.push_back(TLSTEntry);
18591 LocServiceTimesVector.push_back(TLSTEntry);
18602 LocServiceTimesVector.push_back(TLSTEntry);
18605 LocServiceTimesVector.push_back(TLSTEntry);
18622 AnsiString HString;
18623 AnsiString VString;
18626 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18630 HString = AnsiString(HLoc);
18634 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18638 VString = AnsiString(VLoc);
18640 TLSTEntry.
Location = HString +
'-' + VString;
18642 LocServiceTimesVector.push_back(TLSTEntry);
18647 AnsiString FrhTime;
18648 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
18652 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
18660 LocServiceTimesVector.push_back(TLSTEntry);
18666 LocServiceTimesVector.push_back(TLSTEntry);
18671 else if(AVE.
Command ==
"Frh-sh")
18673 if(y == NumTrains - 1)
18679 LocServiceTimesVector.push_back(TLSTEntry);
18685 LocServiceTimesVector.push_back(TLSTEntry);
18698 SequenceLog +=
"5\n";
18731 TLocServiceTimesVector::iterator Ptr1, Ptr2;
18734 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
18735 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
18737 std::ofstream TTFile3(TTFileName3.c_str());
18741 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
18745 if(LocServiceTimesVector.empty())
18747 ShowMessage(
"No timetabled services found");
18749 DeleteFile(TTFileName3);
18753 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n";
18754 TTFile3 <<
"See user manual or on-screen help section 5.12 for detailed information.\n\n\n";
18755 SequenceLog +=
"6\n";
18984 Ptr1 = LocServiceTimesVector.begin();
18986 while(Ptr2 != LocServiceTimesVector.end())
18988 while(Ptr2->Location == Ptr1->Location)
18991 if(Ptr2 == LocServiceTimesVector.end())
18998 if(Ptr2 != LocServiceTimesVector.end())
19006 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
19007 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
19008 MinuteString =
" minutes";
19009 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19012 MinuteString =
" minute";
19014 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
19015 TTFile3 <<
",Platforms,Trains\n\n";
19017 Ptr1 = LocServiceTimesVector.begin();
19019 while(Ptr2 != LocServiceTimesVector.end())
19021 PreviousService =
"";
19022 NumTrainsAtLoc = 0;
19023 ServiceAndRepeatNumTotal =
"";
19025 NumPlatsAtThisLocCalculated =
false;
19027 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19029 PreviousService =
"";
19030 NumTrainsAtLoc = 0;
19031 ServiceAndRepeatNumTotal =
"";
19033 NumPlatsAtThisLocCalculated =
false;
19037 if(Ptr2 == LocServiceTimesVector.end())
19042 if(Ptr2 == LocServiceTimesVector.end())
19046 while(Ptr2->Location == Ptr1->Location)
19048 PreviousService =
"";
19049 NumTrainsAtLoc = 0;
19050 ServiceAndRepeatNumTotal =
"";
19051 BasicTime = Ptr1->ArrTime;
19052 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19056 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
19058 BasicTime = Ptr2->ArrTime;
19061 if(Ptr2 == LocServiceTimesVector.end())
19065 if(Ptr2->Location != Ptr1->Location)
19070 if(Ptr2 == LocServiceTimesVector.end())
19074 if(Ptr2->Location != Ptr1->Location)
19080 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
19084 if(!NumPlatsAtThisLocCalculated)
19087 NumPlatsAtThisLocCalculated =
true;
19089 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19091 if(ServiceAndRepeatNumTotal ==
"")
19093 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19094 NumTrainsAtLoc = 1;
19098 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19101 PreviousService = Ptr2->ServiceAndRepeatNum;
19102 if(ServiceAndRepeatNumTotal ==
"")
19104 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19105 NumTrainsAtLoc = 1;
19109 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19113 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
19115 int MaxNumberOfSameDirections = 0;
19116 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
19121 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19125 AnsiString Asterisk =
"";
19126 if(MaxNumberOfSameDirections >= NumPlats)
19131 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19132 ArrivalsPrinted =
true;
19133 ServiceAndRepeatNumTotal =
"";
19135 if(Ptr2 == LocServiceTimesVector.end())
19139 if(Ptr2->Location != Ptr1->Location)
19144 if(Ptr2 == LocServiceTimesVector.end())
19150 if(!ArrivalsPrinted)
19152 TTFile3 <<
"Nothing to report for arrivals";
19157 SequenceLog +=
"7\n";
19162 Ptr1 = LocServiceTimesVector.begin();
19164 while(Ptr2 != LocServiceTimesVector.end())
19166 while(Ptr2->Location == Ptr1->Location)
19169 if(Ptr2 == LocServiceTimesVector.end())
19176 if(Ptr2 != LocServiceTimesVector.end())
19183 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
19184 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
19185 MinuteString =
" minutes";
19186 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19189 MinuteString =
" minute";
19191 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
19192 TTFile3 <<
",Platforms,Trains\n\n";
19194 Ptr1 = LocServiceTimesVector.begin();
19196 while(Ptr2 != LocServiceTimesVector.end())
19198 PreviousService =
"";
19199 NumTrainsAtLoc = 0;
19200 ServiceAndRepeatNumTotal =
"";
19202 NumPlatsAtThisLocCalculated =
false;
19204 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19206 PreviousService =
"";
19207 NumTrainsAtLoc = 0;
19208 ServiceAndRepeatNumTotal =
"";
19210 NumPlatsAtThisLocCalculated =
false;
19214 if(Ptr2 == LocServiceTimesVector.end())
19219 if(Ptr2 == LocServiceTimesVector.end())
19223 while(Ptr2->Location == Ptr1->Location)
19225 PreviousService =
"";
19226 NumTrainsAtLoc = 0;
19227 ServiceAndRepeatNumTotal =
"";
19228 BasicTime = Ptr1->DepTime;
19229 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19233 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
19235 BasicTime = Ptr2->DepTime;
19238 if(Ptr2 == LocServiceTimesVector.end())
19242 if(Ptr2->Location != Ptr1->Location)
19247 if(Ptr2 == LocServiceTimesVector.end())
19251 if(Ptr2->Location != Ptr1->Location)
19257 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
19261 if(!NumPlatsAtThisLocCalculated)
19264 NumPlatsAtThisLocCalculated =
true;
19266 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19268 if(ServiceAndRepeatNumTotal ==
"")
19270 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19271 NumTrainsAtLoc = 1;
19275 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19278 PreviousService = Ptr2->ServiceAndRepeatNum;
19279 if(ServiceAndRepeatNumTotal ==
"")
19281 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19282 NumTrainsAtLoc = 1;
19286 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19290 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
19292 int MaxNumberOfSameDirections = 0;
19293 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
19298 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19302 AnsiString Asterisk =
"";
19303 if(MaxNumberOfSameDirections >= NumPlats)
19308 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19309 DeparturesPrinted =
true;
19310 ServiceAndRepeatNumTotal =
"";
19312 if(Ptr2 == LocServiceTimesVector.end())
19316 if(Ptr2->Location != Ptr1->Location)
19321 if(Ptr2 == LocServiceTimesVector.end())
19327 if(!DeparturesPrinted)
19329 TTFile3 <<
"Nothing to report for departures";
19334 SequenceLog +=
"8\n";
19341 Ptr1 = LocServiceTimesVector.begin();
19343 while(Ptr2 != LocServiceTimesVector.end())
19345 while(Ptr2->Location == Ptr1->Location)
19348 if(Ptr2 == LocServiceTimesVector.end())
19355 if(Ptr2 != LocServiceTimesVector.end())
19362 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
19363 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
19364 TTFile3 <<
",Platforms,Trains,\n\n";
19365 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19366 Ptr1 = LocServiceTimesVector.begin();
19368 while(Ptr2 != LocServiceTimesVector.end())
19370 PreviousService =
"";
19371 ServiceAndRepeatNumTotal =
"";
19372 NumTrainsAtLoc = 0;
19374 NumPlatsAtThisLocCalculated =
false;
19377 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19379 PreviousService =
"";
19380 ServiceAndRepeatNumTotal =
"";
19381 NumTrainsAtLoc = 0;
19383 NumPlatsAtThisLocCalculated =
false;
19387 if(Ptr2 == LocServiceTimesVector.end())
19392 if(Ptr2 == LocServiceTimesVector.end())
19396 while(Ptr2->Location == Ptr1->Location)
19398 if(Ptr1->FrhMarker ==
"Frh")
19401 Ptr1->FrhMarker =
"FrhCounted";
19403 PreviousService =
"";
19404 NumTrainsAtLoc = 0;
19405 ServiceAndRepeatNumTotal =
"";
19406 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19410 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
19413 if(Ptr1->FrhMarker ==
"Frh")
19416 Ptr1->FrhMarker =
"FrhCounted";
19419 if(Ptr2 == LocServiceTimesVector.end())
19423 if(Ptr2->Location != Ptr1->Location)
19428 if(Ptr2 == LocServiceTimesVector.end())
19432 if(Ptr2->Location != Ptr1->Location)
19436 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
19438 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
19442 if(!NumPlatsAtThisLocCalculated)
19445 NumPlatsAtThisLocCalculated =
true;
19447 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19449 if(ServiceAndRepeatNumTotal ==
"")
19451 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
19452 NumTrainsAtLoc = 1;
19456 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
19459 PreviousService = Ptr2->ServiceAndRepeatNum;
19460 if(ServiceAndRepeatNumTotal ==
"")
19462 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
19463 NumTrainsAtLoc = 1;
19467 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
19470 if(Ptr1->FrhMarker ==
"Frh")
19473 Ptr1->FrhMarker =
"FrhCounted";
19476 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
19480 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
19482 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
19484 AnsiString Asterisk =
"";
19485 if(NumTrainsAtLoc > NumPlats)
19492 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19494 else if(FrhCount == 1)
19496 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19500 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19502 LastFrhCount = FrhCount;
19503 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
19504 AtLocsPrinted =
true;
19505 ServiceAndRepeatNumTotal =
"";
19508 if(Ptr2 == LocServiceTimesVector.end())
19512 if(Ptr2->Location != Ptr1->Location)
19517 if(Ptr2 == LocServiceTimesVector.end())
19525 TTFile3 <<
"Nothing to report for trains at locations";
19530 SequenceLog +=
"9\n";
19564 TTrainDataEntry SingleServiceEntry, PartServiceEntry, NewPartServiceEntry, TempEntry;
19569 TTFile3 <<
"Train direction analysis - consisting of train facing directions on creation and possible missing or questionable changes of direction:\n\n";
19578 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
19580 SingleServiceEntry = TDE;
19582 for(
unsigned int y = 0; y < SSAV.size(); y++)
19584 if((SSAV.at(y).Command ==
"Fjo") || (SSAV.at(y).Command ==
"Frh") || (SSAV.at(y).Command ==
"Fer") || (SSAV.at(y).Command ==
"Frh-sh"))
19586 SingleServiceVector.push_back(SingleServiceEntry);
19589 else if((SSAV.at(y).Command ==
"fsp") || (SSAV.at(y).Command ==
"rsp"))
19591 PartServiceEntry = TDE;
19593 for(
unsigned int z = 0; z <= y; z++)
19598 PartServiceEntry.
ActionVector.at(z).Command =
"chr-sp";
19599 PartServiceEntry.
ActionVector.at(z).OtherHeadCode = PartServiceEntry.
ActionVector.at(z).LinkedTrainEntryPtr->ServiceReference;
19602 PartServiceVector.push_back(PartServiceEntry);
19603 if(SSAV.at(y).Command ==
"fsp")
19605 SSAV.at(y).Command =
"Front split - original service continues below";
19606 SSAV.at(y).OtherHeadCode =
"";
19608 if(SSAV.at(y).Command ==
"rsp")
19610 SSAV.at(y).Command =
"Rear split - original service continues below";
19611 SSAV.at(y).OtherHeadCode =
"";
19615 else if(SSAV.at(y).Command ==
"Fns")
19617 SSAV.at(y).Command =
"chr-Fns";
19618 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
19619 PartServiceVector.push_back(SingleServiceEntry);
19622 else if(SSAV.at(y).Command ==
"Fns-sh")
19624 SSAV.at(y).Command =
"chr-Fns-sh";
19625 SSAV.at(y).OtherHeadCode = SSAV.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19626 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19627 PartServiceVector.push_back(SingleServiceEntry);
19630 else if(SSAV.at(y).Command ==
"F-nshs")
19632 SSAV.at(y).Command =
"chr-F-nshs";
19633 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
19634 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19635 PartServiceVector.push_back(SingleServiceEntry);
19641 SequenceLog +=
"10\n";
19645 AnsiString NextRef;
19646 while(!PartServiceVector.empty())
19648 PartServiceEntry = PartServiceVector.at(0);
19649 for(
unsigned int y = 0; y < PartServiceEntry.
ActionVector.size(); y++)
19651 if(PartServiceEntry.
ActionVector.at(y).Command.SubString(1,3) ==
"chr")
19653 NextRef = PartServiceEntry.
ActionVector.at(y).OtherHeadCode;
19657 bool FinishType =
true, FoundFlag =
false;
19664 for(
unsigned int y = 1; y < TempEntry.
ActionVector.size(); y++)
19668 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19672 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19678 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19679 SingleServiceVector.push_back(PartServiceVector.at(0));
19680 PartServiceVector.erase(PartServiceVector.begin());
19685 NewPartServiceEntry = PartServiceVector.at(0);
19689 PartServiceVector.push_back(NewPartServiceEntry);
19692 TempEntry.
ActionVector.at(y).Command =
"Front split - original service continues below";
19697 TempEntry.
ActionVector.at(y).Command =
"Rear split - original service continues below";
19700 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19702 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns")
19705 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
19707 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19710 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns-sh")
19713 TempEntry.
ActionVector.at(y).OtherHeadCode = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19714 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19715 NextRef = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19716 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19719 else if(TempEntry.
ActionVector.at(y).Command ==
"F-nshs")
19723 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19724 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
19725 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19733 SequenceLog += +
"11\n";
19734 throw Exception(
"Unable to find service reference " + NextRef +
" Last ref checked = " + TempEntry.
ServiceReference);
19738 if(!PartServiceVector.empty())
19740 SequenceLog +=
"12\n";
19741 throw Exception(
"PartServiceVector should be empty here - size = " + AnsiString(PartServiceVector.size()));
19743 SequenceLog +=
"13\n";
19790 bool BufferFacingUnReportedFlag =
true;
19791 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19797 SequenceLog +=
"13a\n";
19798 throw Exception(
"Repeat entry present in SingleServiceVector at position " + AnsiString(x));
19801 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
19803 bool BufferFlag =
false;
19804 int FrontTVPos = AV.at(0).FrontStartOrRepeatDigits;
19805 int RearTVPos = AV.at(0).RearStartOrRepeatMins;
19806 AnsiString FrontLocName = AV.at(0).LocationName;
19807 int NextEntryPos, NextExitPos;
19810 if(ThisElement.
Conn[0] == RearTVPos)
19814 else if(ThisElement.
Conn[1] == RearTVPos)
19818 else if(ThisElement.
Conn[2] == RearTVPos)
19822 else if(ThisElement.
Conn[3] == RearTVPos)
19834 if(ThisElement.
Conn[ThisExitPos] == -1)
19836 SequenceLog =
"13b\n";
19837 throw Exception(
"ThisElement connects to -1 for " + TDE.
ServiceReference);
19840 NextEntryPos = ThisElement.
ConnLinkPos[ThisExitPos];
19841 if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 0) || (NextEntryPos == 2)))
19843 BufferFlag =
false;
19848 BufferFlag =
false;
19853 BufferFlag =
false;
19861 else if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 1) || (NextEntryPos == 3)))
19863 ThisElement = NextElement;
19869 if(NextEntryPos == 0)
19873 else if(NextEntryPos == 1)
19877 else if(NextEntryPos == 2)
19881 else if(NextEntryPos == 3)
19886 ThisElement = NextElement;
19887 ThisExitPos = NextExitPos;
19892 if(BufferFacingUnReportedFlag)
19894 TTFile3 <<
"Train facing direction on creation analysis:-\n\n";
19895 BufferFacingUnReportedFlag =
false;
19897 TTFile3 <<
"Service " + TDE.
ServiceReference +
" facing buffers on creation\n";
19901 if(BufferFacingUnReportedFlag)
19903 TTFile3 <<
"Nothing to report for train facing directions\n\n";
19909 SequenceLog +=
"13c\n";
19912 AnsiString LocationNameToBeChecked =
"";
19913 bool MissingcdtUnreportedFlag =
true;
19915 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19918 unsigned int y = 0;
19919 int FirstInstance = 9999, SecondInstance = 9999;
19920 bool FullBreak =
false;
19921 MarkerList.clear();
19928 while((y < TDEntry.
ActionVector.size()) && !FullBreak)
19937 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
19939 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
19944 (AVEntry.
Command ==
"Frh-sh"))
19959 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
19965 if(TDEntry.
ActionVector.at(a).LocationName == LocationNameToBeChecked)
19967 SecondInstance = a;
19969 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
19971 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
19973 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
19976 if(MissingcdtUnreportedFlag)
19978 TTFile3 <<
"Possibly missing changes of direction - these will be missing unless the service travels in a loop back to the locations marked:-\n\n";
19980 TTFile3 << LocationNameToBeChecked <<
" is listed twice with no direction change between in service sequence: " << Sequence <<
"\n\n";
19981 MarkerList.push_back(FirstInstance);
19982 MarkerList.push_back(SecondInstance);
19984 MissingcdtUnreportedFlag =
false;
19995 if(MissingcdtUnreportedFlag)
19997 TTFile3 <<
"Nothing to report for missing changes of direction\n\n";
20003 SequenceLog +=
"14\n";
20012 typedef std::list<AnsiString> TLocList;
20013 TLocList BackwardList, ForwardList;
20014 bool IntroLineNeeded =
true;
20015 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
20017 unsigned int cdtPosition = 9999;
20018 AnsiString cdtLocation =
"";
20019 bool FoundSameName =
false;
20020 MarkerList.clear();
20022 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
20025 BackwardList.clear();
20026 ForwardList.clear();
20030 (AVEntry.
Command ==
"Frh-sh"))
20032 if(MarkerList.empty())
20039 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
20041 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
20043 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
20047 if(IntroLineNeeded)
20049 TTFile3 <<
"Questionable change of direction analysis.\n\n";
20050 TTFile3 <<
"For marked changes of direction there are no same-name locations listed both above (up to the start or another direction change)\n";
20051 TTFile3 <<
"and below (down to the end or another direction change) but not counting the change of direction location itself.\n\n";
20052 TTFile3 <<
"These changes of direction are probably valid for movements to and from depots but all should be checked to\n";
20053 TTFile3 <<
"make sure that none has been included incorrectly:\n\n";
20054 IntroLineNeeded =
false;
20056 TTFile3 <<
"Service sequence " << Sequence <<
" contains questionable changes of direction:-\n\n";
20068 for(
int z = y - 1; z >= 0; z--)
20071 if(AVEntry2.
Command ==
"cdt")
20080 BackwardList.sort();
20081 BackwardList.unique();
20082 for(
unsigned int z = y + 1; z < TDEntry.
ActionVector.size(); z++)
20096 ForwardList.sort();
20097 ForwardList.unique();
20098 FoundSameName =
false;
20100 if(!BackwardList.empty() && !ForwardList.empty())
20102 for(TLocList::iterator BLIt = BackwardList.begin(); BLIt != BackwardList.end(); BLIt++)
20104 for(TLocList::iterator FLIt = ForwardList.begin(); FLIt != ForwardList.end(); FLIt++)
20108 FoundSameName =
true;
20115 MarkerList.push_back(cdtPosition);
20119 if(IntroLineNeeded)
20121 TTFile3 <<
"Nothing to report for questionable changes of direction\n\n";
20139 SequenceLog +=
"15\n";
20145 catch(
const Exception &e)
20147 AnsiString TTErrorFileName =
"Analysis Error.txt";
20148 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
20149 std::ofstream TTError(TTErrorFileName.c_str());
20152 ShowMessage(
"Analysis error file failed to open - can't be created");
20156 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
20157 TTError << TimeNow.c_str() <<
'\n' << ArrRange <<
'\n' << ArrChecked <<
'\n' << DepRange <<
'\n' <<
20158 DepChecked <<
'\n' << AtLocChecked <<
'\n' << SequenceLog <<
'\n' << AnsiString(e.Message);
20161 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
20171 if((SSVectorNumber < 0) || ((
unsigned int)SSVectorNumber >= SingleServiceVector.size()))
20173 throw Exception(
"SSVectorNumber out of range, = " + AnsiString(SSVectorNumber) +
", Vector size = " + SingleServiceVector.size());
20175 TTrainDataEntry SingleService = SingleServiceVector.at(SSVectorNumber);
20177 VecFile <<
",Initial service reference " << SingleService.
ServiceReference +
'\n';
20178 AnsiString Marker =
"";
20179 for(
unsigned int x = 0; x < SingleService.
ActionVector.size(); x++)
20182 for(
TNumListIterator MLIt = MarkerList.begin(); MLIt != MarkerList.end(); MLIt++)
20184 if(
int(x) == *MLIt)
20214 if(AVE.
Command.SubString(1,3) ==
"chr")
20223 AVE.
Command =
"Change of service to ";
20225 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"Fns-sh")
20227 AVE.
Command =
"Change to shuttle finishing service";
20229 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"F-nshs")
20256 AnsiString ListOfExits =
"";
20265 VecFile << Marker <<
"Frh" <<
'\n';
20280 for(
unsigned int x = 0; x < Vector.size(); x++)
20283 if(Vector.at(x).ServiceReference == HeadCode)
20285 if(Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1).FormatType ==
Repeat)
20287 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 2);
20290 FinishType =
false;
20295 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1);
20298 FinishType =
false;
20303 return(Vector.at(x));
20307 return(Vector.at(Vector.size() - 1));
20316 if((Time1 ==
"") || (Time2 ==
""))
20321 int Mins = Time1.SubString(4,2).ToInt();
20322 int Hours = Time1.SubString(1,2).ToInt();
20323 int Time1Mins = (Hours * 60) + Mins;
20324 Mins = Time2.SubString(4,2).ToInt();
20325 Hours = Time2.SubString(1,2).ToInt();
20326 int Time2Mins = (Hours * 60) + Mins;
20327 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
20339 bool &AnalysisError,
int &MaxNumberOfSameDirections)
20346 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
20348 std::list<AnsiString> ServiceList;
20350 bool EvenComma =
false;
20351 for(
int x = 1; x <= Input.Length(); x++)
20353 TempStr1 = Input[x];
20354 if(TempStr1 == AnsiString(
',') && EvenComma)
20360 TempStr2 += Input[x];
20362 if(TempStr1 == AnsiString(
','))
20364 EvenComma = !EvenComma;
20368 while(TempStr2.Length() > 0)
20370 SCPos = TempStr2.Pos(
';');
20373 OneService = TempStr2.SubString(1, SCPos - 1);
20374 ServiceList.push_back(OneService);
20375 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
20379 ServiceList.push_back(TempStr2);
20383 ServiceList.sort();
20384 ServiceList.unique();
20385 NumTrainsAtLoc = ServiceList.size();
20388 int DirectionMarker = 0;
20390 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
20392 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20394 *SLIt = *SLIt +
"&0";
20396 SLIt3 = ServiceList.end();
20398 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
20399 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
20400 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
20402 MaxNumberOfSameDirections = 0;
20403 int SameDirectionCount = 0;
20405 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
20409 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
20415 CommaPos1 = SLIt1->Pos(
',');
20416 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
20418 SpacePos = ServiceRef1.Pos(
' ');
20422 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
20423 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
20424 if(RepeatInfo1[1] ==
'F')
20430 SpacePos = RepeatInfo1.Pos(
' ');
20431 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
20434 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
20436 AmpersandPos = AnsiTime1.Pos(
'&');
20437 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
20442 throw Exception(
"ASCLIt1 Error in " + Input);
20444 ServiceCallingLocsList1 = ASCLIt1->second;
20445 AmpersandPos = SLIt1->Pos(
'&');
20446 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
20447 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
20449 SameDirectionCount = 1;
20450 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
20452 CommaPos2 = SLIt2->Pos(
',');
20453 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
20455 SpacePos = ServiceRef2.Pos(
' ');
20459 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
20460 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
20461 if(RepeatInfo2[1] ==
'F')
20467 SpacePos = RepeatInfo2.Pos(
' ');
20468 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
20471 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
20473 AmpersandPos = AnsiTime2.Pos(
'&');
20474 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
20479 throw Exception(
"ASCLIt2 Error in " + Input);
20481 ServiceCallingLocsList2 = ASCLIt2->second;
20483 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
20485 int AmpersandPos = SLIt2->Pos(
'&');
20486 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
20487 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
20488 SameDirectionCount++;
20491 if(SameDirectionCount > MaxNumberOfSameDirections)
20493 MaxNumberOfSameDirections = SameDirectionCount;
20498 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
20501 AmpersandPos = SLIt3->Pos(
'&');
20502 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
20503 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
20506 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20509 AmpersandPos = SLIt->Pos(
'&');
20510 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
20511 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
20512 DirectionMarker = DirectionMarkerString.ToInt();
20513 AnsiString DirectionSuffix =
"";
20515 if(DirectionMarker < 27)
20517 c = 64 + DirectionMarker;
20518 DirectionSuffix =
"," + AnsiString(c);
20520 else if(DirectionMarker < 53)
20522 c = 65 + DirectionMarker - 27;
20523 DirectionSuffix =
",A" + AnsiString(c);
20527 DirectionSuffix =
",?";
20529 *SLIt = ServiceWithoutMarker + DirectionSuffix;
20532 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20534 Output = Output + *SLIt +
",";
20536 if(Output.Length() > 0)
20538 Output = Output.SubString(1, Output.Length() - 1);
20544 catch(
const Exception &e)
20546 AnalysisError =
true;
20558 AnsiString InternalInput = Input, Output =
"", OneService =
"";
20560 std::list<AnsiString> ServiceList;
20562 while(InternalInput.Length() > 0)
20564 CommaPos = InternalInput.Pos(
',');
20567 OneService = InternalInput.SubString(1, CommaPos - 1);
20568 ServiceList.push_back(OneService);
20569 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
20573 ServiceList.push_back(InternalInput);
20574 InternalInput =
"";
20578 ServiceList.sort();
20579 ServiceList.unique();
20580 NumTrainsAtLoc = ServiceList.size();
20581 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20583 Output = Output + *SLIt +
",";
20585 if(Output.Length() > 0)
20587 Output = Output.SubString(1, Output.Length() - 1);
20600 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
20602 std::list<AnsiString>::iterator LP1, LP2, ListPtr1, ListPtr2, LocPtr1, LocPtr2;
20607 bool LocFound =
false;
20608 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
20610 TDateTime FirstServiceTime;
20613 int Ref1Target = 0, Ref1Count = 0;
20614 int Ref2Target = 0, Ref2Count = 0;
20632 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
20635 if((*ListPtr1) == Location)
20637 LocPtr1 = ListPtr1;
20640 if(ListPtr1->SubString(1, 3) ==
"%%%")
20642 AnsiString CDTTime = ListPtr1->SubString(4, 5);
20647 FirstServiceTime = TDateTime(-1);
20648 bool BreakFlag =
false;
20651 if(TDVIt->ServiceReference == Ref1)
20653 if(Ref1Target > Ref1Count)
20658 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
20659 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
20663 FirstServiceTime = AVIt->EventTime;
20669 FirstServiceTime = AVIt->ArrivalTime;
20675 FirstServiceTime = AVIt->DepartureTime;
20686 if(IncMinutes == -1)
20688 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20690 if(FirstServiceTime == TDateTime(-1))
20692 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20696 if(!Arrival && (Time1 == CDTTime))
20701 if(Arrival && (Time1 == CDTTime))
20705 if(Time1 > CDTTime)
20710 if(Time1 < CDTTime)
20723 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
20725 if((*ListPtr2) == Location)
20727 LocPtr2 = ListPtr2;
20730 if(ListPtr2->SubString(1, 3) ==
"%%%")
20732 AnsiString CDTTime = ListPtr2->SubString(4, 5);
20737 FirstServiceTime = TDateTime(-1);
20738 bool BreakFlag =
false;
20741 if(TDVIt->ServiceReference == Ref2)
20743 if(Ref2Target > Ref2Count)
20748 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
20749 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
20753 FirstServiceTime = AVIt->EventTime;
20759 FirstServiceTime = AVIt->ArrivalTime;
20765 FirstServiceTime = AVIt->DepartureTime;
20776 if(IncMinutes == -1)
20778 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20780 if(FirstServiceTime == TDateTime(-1))
20782 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20786 if(!Arrival && (Time2 == CDTTime))
20791 if(Arrival && (Time2 == CDTTime))
20795 if(Time2 > CDTTime)
20800 if(Time2 < CDTTime)
20815 LP1 = List1.begin();
20817 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
20819 if(ListPtr1 == List1.begin())
20823 if(ListPtr1->SubString(1, 3) ==
"%%%")
20830 LP2 = List2.begin();
20832 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
20834 if(ListPtr2 == List2.begin())
20838 if(ListPtr2->SubString(1, 3) ==
"%%%")
20848 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
20850 if(ListPtr1 == LocPtr1)
20854 if(ListPtr1->SubString(1, 3) ==
"%%%")
20858 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
20860 if(ListPtr2 == LocPtr2)
20864 if(ListPtr2->SubString(1, 3) ==
"%%%")
20868 if((*ListPtr1) == (*ListPtr2))
20885 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
20887 if(ListPtr1 == List1.end())
20891 if(ListPtr1->SubString(1, 3) ==
"%%%")
20895 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
20897 if(ListPtr2 == List2.end())
20901 if(ListPtr2->SubString(1, 3) ==
"%%%")
20905 if((*ListPtr1) == (*ListPtr2))
20922 if(ExitList.empty())
20928 AnsiString ExitLocList =
"";
20931 unsigned int Counter = 0;
20932 for(
TNumListIterator ELIt = ExitList.begin(); ELIt != ExitList.end(); ELIt++)
20936 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
20938 ExitLocList +=
"\n";
20941 if(StartName ==
"")
20943 if(ExitList.size() == 1)
20947 return(
" at " + ID);
20952 if(ExitList.size() < 4)
20954 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
20959 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
20964 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
20969 if(ExitList.size() < 4)
20971 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
20976 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
20982 if(ExitList.size() < 4)
20984 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
20985 return(
" at " + StartName);
20989 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
20990 return(
" at " + StartName);
21030 AnsiString FormatStr =
"####0.0";
21031 AnsiString AvLateArrMins =
"";
21032 AnsiString AvEarlyArrMins =
"";
21033 AnsiString AvLatePassMins =
"";
21034 AnsiString AvEarlyPassMins =
"";
21035 AnsiString AvLateDepMins =
"";
21036 AnsiString AvLateExitMins =
"";
21037 AnsiString AvEarlyExitMins =
"";
21040 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21073 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
21074 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
21086 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
21090 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
21098 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
21102 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
21110 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
21118 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
21122 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
21126 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
21130 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
21134 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
21138 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
21143 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
21147 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
21151 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
21155 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
21159 PerfFile <<
LateExits <<
" late exits" <<
'\n';
21163 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
21167 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
21171 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
21176 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
21180 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
21184 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
21188 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
21192 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
21194 TDateTime TempExcessLCDownTime;
21208 if(TempExcessLCDownTime > TDateTime(0))
21214 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
21218 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
21226 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
21230 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
21266 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
21270 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
21276 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
21280 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
21283 AnsiString AvLateMinsLocsNotReached =
"";
21289 if(LocsNotReached > 0)
21292 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
21296 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
21300 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
21312 PerfFile <<
Derailments <<
" derailments" <<
'\n';
21316 PerfFile <<
Derailments <<
" derailment" <<
'\n';
21326 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
21328 bool DerailSPADFlag =
false, CrashFlag =
false;
21330 int OverallScorePercent = 100;
21331 int TotArrDepExit = 0;
21332 double TotLateMinsFactor = 1;
21333 double MissedStopAndSPADRiskFactor = 1;
21334 double NetNegFactor = 1;
21344 OverallScorePercent = 5;
21345 DerailSPADFlag =
true;
21349 OverallScorePercent = 0;
21352 if(OverallScorePercent == 100)
21357 LatenessPenalty = 0;
21363 if(TotArrDepExit > 0)
21372 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
21374 OverallScorePercent = 100 * NetNegFactor;
21377 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
21380 AnsiString OneFailureString =
", though the failure would account for some poor performance";
21381 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
21382 AnsiString AddedString =
"";
21385 AddedString = OneFailureString;
21389 AddedString = TwoOrMoreFailureString;
21391 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
21392 AnsiString Rating =
"";
21393 if(OverallScorePercent == 100)
21395 Rating =
"Perfect!";
21397 else if(OverallScorePercent >= 95)
21399 Rating =
"Excellent";
21401 else if(OverallScorePercent >= 90)
21403 Rating =
"Very good";
21405 else if(OverallScorePercent >= 80)
21409 else if(OverallScorePercent >= 70)
21413 else if(OverallScorePercent >= 60)
21415 Rating =
"Unacceptable" + AddedString;
21417 else if(OverallScorePercent >= 50)
21419 Rating =
"Poor" + AddedString;
21421 else if(OverallScorePercent >= 40)
21423 Rating =
"Bad" + AddedString;
21425 else if(OverallScorePercent >= 30)
21427 Rating =
"Very bad" + AddedString;
21429 else if(OverallScorePercent >= 20)
21431 Rating =
"Terrible" + AddedString;
21433 else if(OverallScorePercent >= 10)
21435 Rating =
"Appalling" + AddedString;
21437 else if(OverallScorePercent >= 5)
21441 Rating =
"Disastrous - potential loss of life";
21446 Rating =
"Dire" + AddedString;
21449 else if(OverallScorePercent < 5)
21453 Rating =
"Catastrophic - loss of life";
21457 Rating =
"Abysmal";
21460 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
21464 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
21466 PerfFile <<
'\n' <<
"***************************************";
21476 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21526 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21561 int IncrementalMinutes = 0;
21575 bool TrainOperatingFlag =
false;
21580 TrainOperatingFlag =
true;
21584 if(TrainOperatingFlag)
21592 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
21639 AnsiString HeadCode;
21643 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21647 HCandTrainPosParam.first = HeadCode;
21648 HCandTrainPosParam.second = TrainID;
21650 if((TimeToAct >= 0) && (TimeToAct < 59.9))
21653 OpTimeToActMultiMapEntry.first = TimeToAct;
21654 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
21683 float TimeToAct = 0;
21684 int DistanceToRedSignal = 0;
21687 ContinuationEntryVecPosVector.clear();
21688 bool LaterTrain =
false;
21692 LaterTrain =
false;
21693 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
21704 if(!ContinuationEntryVecPosVector.empty())
21706 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
21708 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
21722 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
21723 AnsiString HeadCode = CTEIt->second.HeadCode;
21724 float CurrentStopTime;
21725 float LaterStopTime;
21726 float RecoverableTime;
21729 int DistanceToExit;
21731 bool SigControlAndCanPassRedSignal =
false;
21739 if(CTEIt->second.TrainDataEntryPtr->ActionVector.size() == 1)
21745 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(AtValue),
21746 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed, DistanceToExit, ExitPair);
21749 if(AvTrackSpeed < 30)
21753 if(DistanceToRedSignal == -1)
21759 int Speed = AvTrackSpeed;
21760 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
21761 if(AvTrackSpeed > MaxSpeed)
21765 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(0).SignallerControl)
21768 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
21771 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
21776 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
21777 TimeToAct += MinsBefEnter;
21780 HCandTrainPosParam.first = HeadCode;
21781 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
21784 if(TimeToAct < 59.9)
21786 OpTimeToActMultiMapEntry.first = TimeToAct;
21787 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
21812 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21822 TimeToExitMultiMapEntry.first = ExitPair;
21823 TimeToExitMultiMapEntry.second = ExitInfo;
21833 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
21834 float &RecoverableTime,
int &AvTrackSpeed,
int &DistanceToExit,
THVShortPair &ExitPair)
21843 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
21844 int DistanceToRedSignal = 0;
21845 DistanceToExit = -1;
21846 ExitPair.first = -1;
21847 ExitPair.second = -1;
21848 int CumTrackSpeed = 0;
21850 int TrackSpeedCount = 0;
21851 float KmPerLocationStop;
21852 float MaxAllowableSpeed;
21862 int CurrentElement = TrackVectorPosition;
21863 int CurrentEntryPos = TrackVectorPositionEntryPos;
21868 CurrentStopTime = 0;
21870 RecoverableTime = 0;
21871 if(CurrentElement == -1)
21876 int CurrentExitPos;
21881 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
21885 CurrentExitPos = 1;
21889 CurrentExitPos = 3;
21894 CurrentExitPos = 0;
21931 CurrentStopTime = float(TimeToDepart);
21937 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
21948 else if(SigControlAndCanPassRedSignal)
21953 if((NextEntryPos == 0) || (NextEntryPos == 2))
21974 CurrentElement = NextElement;
21975 CurrentEntryPos = NextEntryPos;
21976 CurrentExitPos = NextExitPos;
21988 int LaterStopNumber = 0;
21992 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
22001 if(CurrentEntryPos > 1)
22016 DistanceToExit = DistanceToRedSignal;
22021 if(TrackSpeedCount > 0)
22023 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22027 if(CurrentEntryPos > 1)
22038 if(LaterStopNumber > 0)
22040 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22041 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22047 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22051 if(AvTrackSpeed > MaxAllowableSpeed)
22053 AvTrackSpeed = MaxAllowableSpeed;
22065 bool StopRequired =
false;
22082 int TrainOnElement;
22089 if(CurrentEntryPos > 1)
22098 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
22107 double StopTimeDouble;
22120 if(StopTimeDouble < 0.5)
22122 StopTimeDouble = 0.5;
22126 LaterStopTime += float(StopTimeDouble);
22127 RecoverableTime += StopTimeDouble - 0.5;
22128 if((LaterStopNumber == 1) && (TrainID > -1))
22136 if((AVPtr + 1)->FormatType ==
TimeLoc)
22140 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
22142 if(StopTimeDouble < 0.5)
22144 StopTimeDouble = 0.5;
22147 LaterStopTime += float(StopTimeDouble);
22148 RecoverableTime += StopTimeDouble - 0.5;
22149 if((LaterStopNumber == 1) && (TrainID > -1))
22165 if(NextElement == -1)
22174 if((NextEntryPos == 0) || (NextEntryPos == 2))
22195 CurrentElement = NextElement;
22196 CurrentEntryPos = NextEntryPos;
22197 CurrentExitPos = NextExitPos;
22202 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
22215 if(TrackSpeedCount > 0)
22217 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22221 if(CurrentEntryPos > 1)
22232 if(LaterStopNumber > 0)
22234 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22235 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22241 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22245 if(AvTrackSpeed > MaxAllowableSpeed)
22247 AvTrackSpeed = MaxAllowableSpeed;
22250 return(DistanceToRedSignal);